diff --git a/Engine/source/T3D/containerQuery.cpp b/Engine/source/T3D/containerQuery.cpp index 1c3f34609..1c5f1bc90 100644 --- a/Engine/source/T3D/containerQuery.cpp +++ b/Engine/source/T3D/containerQuery.cpp @@ -20,6 +20,11 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// +// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames +// Copyright (C) 2015 Faust Logic, Inc. +//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// + #include "platform/platform.h" #include "T3D/containerQuery.h" @@ -91,7 +96,9 @@ void physicalZoneFind(SceneObject* obj, void *key) if (pz->isActive()) { info->gravityScale *= pz->getGravityMod(); - info->appliedForce += pz->getForce(); + Point3F center; + info->box.getCenter(¢er); + info->appliedForce += pz->getForce(¢er); } } diff --git a/Engine/source/T3D/physicalZone.cpp b/Engine/source/T3D/physicalZone.cpp index f7307ef21..b9301d0da 100644 --- a/Engine/source/T3D/physicalZone.cpp +++ b/Engine/source/T3D/physicalZone.cpp @@ -20,6 +20,11 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// +// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames +// Copyright (C) 2015 Faust Logic, Inc. +//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// + #include "T3D/physicalZone.h" #include "core/stream/bitStream.h" #include "collision/boxConvex.h" @@ -33,6 +38,8 @@ #include "gfx/gfxDrawUtil.h" #include "console/engineAPI.h" +//#include "console/engineTypes.h" +#include "sim/netConnection.h" IMPLEMENT_CO_NETOBJECT_V1(PhysicalZone); ConsoleDocClass( PhysicalZone, @@ -103,6 +110,10 @@ PhysicalZone::PhysicalZone() mConvexList = new Convex; mActive = true; + force_type = VECTOR; + force_mag = 0.0f; + orient_force = false; + fade_amt = 1.0f; } PhysicalZone::~PhysicalZone() @@ -111,6 +122,16 @@ PhysicalZone::~PhysicalZone() mConvexList = NULL; } + +ImplementEnumType( PhysicalZone_ForceType, "Possible physical zone force types.\n" "@ingroup PhysicalZone\n\n" ) + { PhysicalZone::VECTOR, "vector", "..." }, + { PhysicalZone::SPHERICAL, "spherical", "..." }, + { PhysicalZone::CYLINDRICAL, "cylindrical", "..." }, + // aliases + { PhysicalZone::SPHERICAL, "sphere", "..." }, + { PhysicalZone::CYLINDRICAL, "cylinder", "..." }, +EndImplementEnumType; + //-------------------------------------------------------------------------- void PhysicalZone::consoleInit() { @@ -129,6 +150,10 @@ void PhysicalZone::initPersistFields() "point followed by three vectors representing the edges extending from the corner." ); endGroup("Misc"); + addGroup("AFX"); + addField("forceType", TYPEID(), Offset(force_type, PhysicalZone)); + addField("orientForce", TypeBool, Offset(orient_force, PhysicalZone)); + endGroup("AFX"); Parent::initPersistFields(); } @@ -158,6 +183,19 @@ bool PhysicalZone::onAdd() Polyhedron temp = mPolyhedron; setPolyhedron(temp); + switch (force_type) + { + case SPHERICAL: + force_mag = mAppliedForce.magnitudeSafe(); + break; + case CYLINDRICAL: + { + Point3F force_vec = mAppliedForce; + force_vec.z = 0.0; + force_mag = force_vec.magnitudeSafe(); + } + break; + } addToScene(); return true; @@ -191,7 +229,7 @@ void PhysicalZone::setTransform(const MatrixF & mat) mClippedList.setBaseTransform(base); if (isServerObject()) - setMaskBits(InitialUpdateMask); + setMaskBits(MoveMask); } @@ -242,12 +280,8 @@ U32 PhysicalZone::packUpdate(NetConnection* con, U32 mask, BitStream* stream) U32 i; U32 retMask = Parent::packUpdate(con, mask, stream); - if (stream->writeFlag((mask & InitialUpdateMask) != 0)) { - // Note that we don't really care about efficiency here, since this is an - // edit-only ghost... - mathWrite(*stream, mObjToWorld); - mathWrite(*stream, mObjScale); - + if (stream->writeFlag(mask & PolyhedronMask)) + { // Write the polyhedron stream->write(mPolyhedron.pointList.size()); for (i = 0; i < mPolyhedron.pointList.size(); i++) @@ -266,15 +300,33 @@ U32 PhysicalZone::packUpdate(NetConnection* con, U32 mask, BitStream* stream) stream->write(rEdge.vertex[0]); stream->write(rEdge.vertex[1]); } + } + if (stream->writeFlag(mask & MoveMask)) + { + stream->writeAffineTransform(mObjToWorld); + mathWrite(*stream, mObjScale); + } + + if (stream->writeFlag(mask & SettingsMask)) + { stream->write(mVelocityMod); stream->write(mGravityMod); mathWrite(*stream, mAppliedForce); - stream->writeFlag(mActive); - } else { - stream->writeFlag(mActive); + stream->writeInt(force_type, FORCE_TYPE_BITS); + stream->writeFlag(orient_force); } + if (stream->writeFlag(mask & FadeMask)) + { + U8 fade_byte = (U8)(fade_amt*255.0f); + stream->write(fade_byte); + } + + stream->writeFlag(mActive); + + // AFX CODE BLOCK (enhanced-physical-zone)(pz-opt) >> + return retMask; } @@ -282,16 +334,12 @@ void PhysicalZone::unpackUpdate(NetConnection* con, BitStream* stream) { Parent::unpackUpdate(con, stream); - if (stream->readFlag()) { + bool new_ph = false; + if (stream->readFlag()) // PolyhedronMask + { U32 i, size; - MatrixF temp; - Point3F tempScale; Polyhedron tempPH; - // Transform - mathRead(*stream, &temp); - mathRead(*stream, &tempScale); - // Read the polyhedron stream->read(&size); tempPH.pointList.setSize(size); @@ -314,17 +362,46 @@ void PhysicalZone::unpackUpdate(NetConnection* con, BitStream* stream) stream->read(&rEdge.vertex[1]); } + setPolyhedron(tempPH); + new_ph = true; + } + + if (stream->readFlag()) // MoveMask + { + MatrixF temp; + stream->readAffineTransform(&temp); + + Point3F tempScale; + mathRead(*stream, &tempScale); + + //if (!new_ph) + //{ + // Polyhedron rPolyhedron = mPolyhedron; + // setPolyhedron(rPolyhedron); + //} + setScale(tempScale); + setTransform(temp); + } + + if (stream->readFlag()) //SettingsMask + { stream->read(&mVelocityMod); stream->read(&mGravityMod); mathRead(*stream, &mAppliedForce); - - setPolyhedron(tempPH); - setScale(tempScale); - setTransform(temp); - mActive = stream->readFlag(); - } else { - mActive = stream->readFlag(); + force_type = stream->readInt(FORCE_TYPE_BITS); // AFX + orient_force = stream->readFlag(); // AFX } + + if (stream->readFlag()) //FadeMask + { + U8 fade_byte; + stream->read(&fade_byte); + fade_amt = ((F32)fade_byte)/255.0f; + } + else + fade_amt = 1.0f; + + mActive = stream->readFlag(); } @@ -443,3 +520,104 @@ void PhysicalZone::deactivate() mActive = false; } +void PhysicalZone::onStaticModified(const char* slotName, const char*newValue) +{ + if (dStricmp(slotName, "appliedForce") == 0 || dStricmp(slotName, "forceType") == 0) + { + switch (force_type) + { + case SPHERICAL: + force_mag = mAppliedForce.magnitudeSafe(); + break; + case CYLINDRICAL: + { + Point3F force_vec = mAppliedForce; + force_vec.z = 0.0; + force_mag = force_vec.magnitudeSafe(); + } + break; + } + } +} + +const Point3F& PhysicalZone::getForce(const Point3F* center) const +{ + static Point3F force_vec; + + if (force_type == VECTOR) + { + if (orient_force) + { + getTransform().mulV(mAppliedForce, &force_vec); + force_vec *= fade_amt; + return force_vec; + } + force_vec = mAppliedForce; + force_vec *= fade_amt; + return force_vec; + } + + if (!center) + { + force_vec.zero(); + return force_vec; + } + + if (force_type == SPHERICAL) + { + force_vec = *center - getPosition(); + force_vec.normalizeSafe(); + force_vec *= force_mag*fade_amt; + return force_vec; + } + + if (orient_force) + { + force_vec = *center - getPosition(); + getWorldTransform().mulV(force_vec); + force_vec.z = 0.0f; + force_vec.normalizeSafe(); + force_vec *= force_mag; + force_vec.z = mAppliedForce.z; + getTransform().mulV(force_vec); + force_vec *= fade_amt; + return force_vec; + } + + force_vec = *center - getPosition(); + force_vec.z = 0.0f; + force_vec.normalizeSafe(); + force_vec *= force_mag; + force_vec *= fade_amt; + return force_vec; +} + +bool PhysicalZone::isExcludedObject(SceneObject* obj) const +{ + for (S32 i = 0; i < excluded_objects.size(); i++) + if (excluded_objects[i] == obj) + return true; + + return false; +} + +void PhysicalZone::registerExcludedObject(SceneObject* obj) +{ + if (isExcludedObject(obj)) + return; + + excluded_objects.push_back(obj); + setMaskBits(FadeMask); +} + +void PhysicalZone::unregisterExcludedObject(SceneObject* obj) +{ + for (S32 i = 0; i < excluded_objects.size(); i++) + if (excluded_objects[i] == obj) + { + excluded_objects.erase(i); + setMaskBits(FadeMask); + return; + } +} + diff --git a/Engine/source/T3D/physicalZone.h b/Engine/source/T3D/physicalZone.h index 2f1d72593..004ce6cb3 100644 --- a/Engine/source/T3D/physicalZone.h +++ b/Engine/source/T3D/physicalZone.h @@ -20,6 +20,11 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// +// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames +// Copyright (C) 2015 Faust Logic, Inc. +//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// + #ifndef _H_PHYSICALZONE #define _H_PHYSICALZONE @@ -40,9 +45,14 @@ class PhysicalZone : public SceneObject { typedef SceneObject Parent; - enum UpdateMasks { + enum UpdateMasks { ActiveMask = Parent::NextFreeMask << 0, - NextFreeMask = Parent::NextFreeMask << 1 + SettingsMask = Parent::NextFreeMask << 1, + FadeMask = Parent::NextFreeMask << 2, + PolyhedronMask = Parent::NextFreeMask << 3, + MoveMask = Parent::NextFreeMask << 4, + ExclusionMask = Parent::NextFreeMask << 5, + NextFreeMask = Parent::NextFreeMask << 6 }; protected: @@ -83,7 +93,10 @@ class PhysicalZone : public SceneObject inline F32 getVelocityMod() const { return mVelocityMod; } inline F32 getGravityMod() const { return mGravityMod; } - inline const Point3F& getForce() const { return mAppliedForce; } + // the scene object is now passed in to getForce() where + // it is needed to calculate the applied force when the + // force is radial. + const Point3F& getForce(const Point3F* center=0) const; void setPolyhedron(const Polyhedron&); bool testObject(SceneObject*); @@ -96,7 +109,25 @@ class PhysicalZone : public SceneObject void deactivate(); inline bool isActive() const { return mActive; } +protected: + friend class afxPhysicalZoneData; + friend class afxEA_PhysicalZone; + Vector excluded_objects; + S32 force_type; + F32 force_mag; + bool orient_force; + F32 fade_amt; + void setFadeAmount(F32 amt) { fade_amt = amt; if (fade_amt < 1.0f) setMaskBits(FadeMask); } +public: + enum ForceType { VECTOR, SPHERICAL, CYLINDRICAL }; + enum { FORCE_TYPE_BITS = 2 }; + virtual void onStaticModified(const char* slotName, const char*newValue = NULL); + bool isExcludedObject(SceneObject*) const; + void registerExcludedObject(SceneObject*); + void unregisterExcludedObject(SceneObject*); }; +typedef PhysicalZone::ForceType PhysicalZone_ForceType; +DefineEnumType( PhysicalZone_ForceType ); #endif // _H_PHYSICALZONE