/*==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 <http://www.gnu.org/licenses/>. 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 plPXPhysical_h_inc #define plPXPhysical_h_inc #include "plPhysical.h" #include "hsMatrix44.h" #include "../plPhysical/plSimDefs.h" #include "hsBitVector.h" #include "hsUtils.h" class NxActor; class NxConvexMesh; class NxTriangleMesh; struct hsPoint3; class hsQuat; class plPhysicalProxy; class plDrawableSpans; class hsGMaterial; struct hsPlane3; class plMessage; class plLOSHit; class plSimulationMsg; class plSDLModifier; class plPhysicalSndGroup; class plGenRefMsg; class plSceneObject; class hsVectorStream; class NxCapsule; class PhysRecipe { public: PhysRecipe(); hsScalar mass; hsScalar friction; hsScalar restitution; plSimDefs::Bounds bounds; plSimDefs::Group group; UInt32 reportsOn; plKey objectKey; plKey sceneNode; plKey worldKey; // The local to subworld matrix (or local to world if worldKey is nil) hsMatrix44 l2s; NxConvexMesh* convexMesh; NxTriangleMesh* triMesh; // For spheres only hsScalar radius; hsPoint3 offset; // For Boxes hsPoint3 bDimensions; hsPoint3 bOffset; // For export time only. The original data used to create the mesh hsVectorStream* meshStream; }; class plPXPhysical : public plPhysical { public: friend class plSimulationMgr; enum PhysRefType { kPhysRefWorld, kPhysRefSndGroup }; plPXPhysical(); virtual ~plPXPhysical(); CLASSNAME_REGISTER(plPXPhysical); GETINTERFACE_ANY(plPXPhysical, plPhysical); // Export time and internal use only hsBool Init(PhysRecipe& recipe); virtual void Read(hsStream* s, hsResMgr* mgr); virtual void Write(hsStream* s, hsResMgr* mgr); virtual hsBool MsgReceive(plMessage* msg); // // From plPhysical // virtual plPhysical& SetProperty(int prop, hsBool b); virtual hsBool GetProperty(int prop) const { return fProps.IsBitSet(prop) != 0; } virtual void SetObjectKey(plKey key) { fObjectKey = key; } virtual plKey GetObjectKey() const { return fObjectKey; } virtual void SetSceneNode(plKey node); virtual plKey GetSceneNode() const; virtual hsBool GetLinearVelocitySim(hsVector3& vel) const; virtual void SetLinearVelocitySim(const hsVector3& vel); virtual void ClearLinearVelocity(); virtual hsBool GetAngularVelocitySim(hsVector3& vel) const; virtual void SetAngularVelocitySim(const hsVector3& vel); virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l, hsBool force=false); virtual void GetTransform(hsMatrix44& l2w, hsMatrix44& w2l); virtual int GetGroup() const { return fGroup; } virtual void AddLOSDB(UInt16 flag) { hsSetBits(fLOSDBs, flag); } virtual void RemoveLOSDB(UInt16 flag) { hsClearBits(fLOSDBs, flag); } virtual UInt16 GetAllLOSDBs() { return fLOSDBs; } virtual hsBool IsInLOSDB(UInt16 flag) { return hsCheckBits(fLOSDBs, flag); } virtual hsBool DoDetectorHullWorkaround() { return fSaveTriangles ? true : false; } virtual hsBool Should_I_Trigger(hsBool enter, hsPoint3& pos); virtual hsBool IsObjectInsideHull(const hsPoint3& pos); virtual void SetInsideConvexHull(hsBool inside) { fInsideConvexHull = inside; } virtual plKey GetWorldKey() const { return fWorldKey; } virtual plPhysicalSndGroup* GetSoundGroup() const { return fSndGroup; } virtual void GetPositionSim(hsPoint3& pos) const { IGetPositionSim(pos); } virtual void SendNewLocation(hsBool synchTransform = false, hsBool isSynchUpdate = false); virtual void SetHitForce(const hsVector3& force, const hsPoint3& pos) { fWeWereHit=true; fHitForce = force; fHitPos = pos; } virtual void ApplyHitForce(); virtual void ResetHitForce() { fWeWereHit=false; fHitForce.Set(0,0,0); fHitPos.Set(0,0,0); } virtual void GetSyncState(hsPoint3& pos, hsQuat& rot, hsVector3& linV, hsVector3& angV); virtual void SetSyncState(hsPoint3* pos, hsQuat* rot, hsVector3* linV, hsVector3* angV); virtual void ExcludeRegionHack(hsBool cleared); virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo); hsBool DoReportOn(plSimDefs::Group group) const { return hsCheckBits(fReportsOn, 1<<group); } // Returns true if this object is *really* dynamic. We can have physicals // that are in the dynamic group but are actually animated or something. // This weeds those out. hsBool IsDynamic() const; //Hack to check if there is an overlap with the capsule //this partially for exclude regions vs avatar capsule virtual hsBool OverlapWithCapsule(NxCapsule& cap); virtual hsScalar GetMass() {return fMass;} protected: void IGetPositionSim(hsPoint3& pos) const; void IGetRotationSim(hsQuat& rot) const; void ISetPositionSim(const hsPoint3& pos); void ISetRotationSim(const hsQuat& rot); /** Handle messages about our references. */ hsBool HandleRefMsg(plGenRefMsg * refM); ///////////////////////////////////////////////////////////// // // WORLDS, SUBWORLDS && CONTEXTS // ///////////////////////////////////////////////////////////// void IConvertGroups(UInt32 memberOf, UInt32 reportsOn, UInt32 collideWith); /** See if the object is in a valid, non-overlapping position. A valid overlap is one which is approved by the collision masking code, i.e. my memberOf has no intersection with your bounceOff and vice-versa */ // Set overlapText to get a string naming all the overlapping physicals (that you must delete) hsBool CheckValidPosition(char** overlapText=nil); ///////////////////////////////////////////////////////////// // // NETWORK SYNCHRONIZATION // ///////////////////////////////////////////////////////////// /** Remember that we need to do a synch soon. */ hsBool DirtySynchState(const char* SDLStateName, UInt32 synchFlags ); double GetLastSyncTime() { return fLastSyncTime; } /** Get the simulation transform of the physical, in world coordinates (factoring in the subworld if necessary */ void IGetTransformGlobal(hsMatrix44 &l2w) const; void ISetTransformGlobal(const hsMatrix44& l2w); // Enable/disable collisions and dynamic movement void IEnable(hsBool enable); void IMakeHull(NxConvexMesh* convexMesh, hsMatrix44 l2w); NxActor* fActor; plKey fWorldKey; // either a subworld or nil plSimDefs::Bounds fBoundsType; plSimDefs::Group fGroup; UInt32 fReportsOn; // bit vector for groups we report interactions with UInt16 fLOSDBs; // Which LOS databases we get put into hsBitVector fProps; // plSimulationInterface::plSimulationProperties kept here float fMass; plKey fObjectKey; // the key to our scene object plKey fSceneNode; // the room we're in // PHYSX FIXME - need to create a plasma hull so that we can determine if inside hsPlane3* fWorldHull; UInt32 fHullNumberPlanes; hsPoint3* fSaveTriangles; hsBool fInsideConvexHull; void ISetHullToWorldWTriangles(); inline hsBool ITestPlane(const hsPoint3 &pos, const hsPlane3 &plane) { hsScalar dis = plane.fN.InnerProduct(pos); dis += plane.fD; if (dis == 0.f) return false; if( dis >= 0.f ) return false; return true; } // we need to remember the last matrices we sent to the coordinate interface // so that we can recognize them when we send them back and not reapply them, // which would reactivate our body. inelegant but effective hsMatrix44 fCachedLocal2World; // Syncronization double fLastSyncTime; plSDLModifier* fSDLMod; plPhysicalSndGroup* fSndGroup; hsBool fWeWereHit; hsVector3 fHitForce; hsPoint3 fHitPos; plPhysicalProxy* fProxyGen; // visual proxy for debugging static int fNumberAnimatedPhysicals; static int fNumberAnimatedActivators; }; #endif