Torque3D Documentation / _generateds / physicalZone.cpp

physicalZone.cpp

Engine/source/T3D/physicalZone.cpp

More...

Public Variables

Public Functions

ConsoleDocClass(PhysicalZone , "@brief Physical Zones are areas that modify the player's gravity and/or velocity and/or applied <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">force.\n\n</a>" "The datablock properties determine how the physics, velocity and applied forces affect <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> player who enters this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">zone.\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classphysicalzone/">PhysicalZone</a>(Team1JumpPad) {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "velocityMod=\"1\";" "gravityMod = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "appliedForce = \"0 0 20000\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "polyhedron = \"0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 -1.0000000 0.0000000 0.0000000 0.0000000 1.0000000\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "position = \"273.559 -166.371 249.856\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "rotation = \"0 0 1 13.0216\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "scale = \"8 4.95 28.31\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "isRenderEnabled = \"true\";\n" "canSaveDynamicFields = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "enabled = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">enviroMisc\n</a>" )
DefineEngineMethod(PhysicalZone , activate , void , () , "Activate the physical zone's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">effects.\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// Activate effects <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> specific physical <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">zone.\n</a>" "%thisPhysicalZone.activate();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Datablocks\n</a>" )
DefineEngineMethod(PhysicalZone , deactivate , void , () , "Deactivate the physical zone's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">effects.\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// Deactivate effects <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> specific physical <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">zone.\n</a>" "%thisPhysicalZone.deactivate();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Datablocks\n</a>" )
ImplementEnumType(PhysicalZone_ForceType , "Possible physical zone force <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">types.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">PhysicalZone\n\n</a>" )

Detailed Description

Public Variables

 EndImplementEnumType 

Public Functions

ConsoleDocClass(PhysicalZone , "@brief Physical Zones are areas that modify the player's gravity and/or velocity and/or applied <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">force.\n\n</a>" "The datablock properties determine how the physics, velocity and applied forces affect <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> player who enters this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">zone.\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classphysicalzone/">PhysicalZone</a>(Team1JumpPad) {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "velocityMod=\"1\";" "gravityMod = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "appliedForce = \"0 0 20000\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "polyhedron = \"0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 -1.0000000 0.0000000 0.0000000 0.0000000 1.0000000\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "position = \"273.559 -166.371 249.856\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "rotation = \"0 0 1 13.0216\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "scale = \"8 4.95 28.31\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "isRenderEnabled = \"true\";\n" "canSaveDynamicFields = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "enabled = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">enviroMisc\n</a>" )

DefineEngineMethod(PhysicalZone , activate , void , () , "Activate the physical zone's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">effects.\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// Activate effects <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> specific physical <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">zone.\n</a>" "%thisPhysicalZone.activate();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Datablocks\n</a>" )

DefineEngineMethod(PhysicalZone , deactivate , void , () , "Deactivate the physical zone's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">effects.\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// Deactivate effects <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> specific physical <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">zone.\n</a>" "%thisPhysicalZone.deactivate();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Datablocks\n</a>" )

IMPLEMENT_CO_NETOBJECT_V1(PhysicalZone )

ImplementEnumType(PhysicalZone_ForceType , "Possible physical zone force <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">types.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">PhysicalZone\n\n</a>" )

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
 25// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
 26// Copyright (C) 2015 Faust Logic, Inc.
 27//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
 28
 29#include "T3D/physicalZone.h"
 30#include "core/stream/bitStream.h"
 31#include "collision/boxConvex.h"
 32#include "collision/clippedPolyList.h"
 33#include "console/consoleTypes.h"
 34#include "math/mathIO.h"
 35#include "scene/sceneRenderState.h"
 36#include "T3D/trigger.h"
 37#include "gfx/gfxTransformSaver.h"
 38#include "renderInstance/renderPassManager.h"
 39#include "gfx/gfxDrawUtil.h"
 40#include "console/engineAPI.h"
 41
 42//#include "console/engineTypes.h"
 43#include "sim/netConnection.h"
 44IMPLEMENT_CO_NETOBJECT_V1(PhysicalZone);
 45
 46ConsoleDocClass( PhysicalZone,
 47   "@brief Physical Zones are areas that modify the player's gravity and/or velocity and/or applied force.\n\n"
 48
 49   "The datablock properties determine how the physics, velocity and applied forces affect a player who enters this zone.\n"
 50
 51   "@tsexample\n"
 52      "new PhysicalZone(Team1JumpPad) {\n"
 53         "velocityMod = \"1\";"
 54         "gravityMod = \"0\";\n"
 55         "appliedForce = \"0 0 20000\";\n"
 56         "polyhedron = \"0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 -1.0000000 0.0000000 0.0000000 0.0000000 1.0000000\";\n"
 57         "position = \"273.559 -166.371 249.856\";\n"
 58         "rotation = \"0 0 1 13.0216\";\n"
 59         "scale = \"8 4.95 28.31\";\n"
 60         "isRenderEnabled = \"true\";\n"
 61         "canSaveDynamicFields = \"1\";\n"
 62         "enabled = \"1\";\n"
 63      "};\n"
 64   "@endtsexample\n\n"
 65   "@ingroup enviroMisc\n"
 66);
 67
 68bool PhysicalZone::smRenderPZones = false;
 69
 70DefineEngineMethod(PhysicalZone, activate, void, (),, "Activate the physical zone's effects.\n"
 71                                       "@tsexample\n"
 72                                          "// Activate effects for a specific physical zone.\n"
 73                                          "%thisPhysicalZone.activate();\n"
 74                                       "@endtsexample\n"
 75                                       "@ingroup Datablocks\n"
 76              )
 77{
 78   if (object->isClientObject())
 79      return;
 80
 81   object->activate();
 82}
 83
 84DefineEngineMethod(PhysicalZone, deactivate, void, (),, "Deactivate the physical zone's effects.\n"
 85                                       "@tsexample\n"
 86                                          "// Deactivate effects for a specific physical zone.\n"
 87                                          "%thisPhysicalZone.deactivate();\n"
 88                                       "@endtsexample\n"
 89                                       "@ingroup Datablocks\n"
 90              )
 91{
 92   if (object->isClientObject())
 93      return;
 94
 95   object->deactivate();
 96}
 97
 98
 99//--------------------------------------------------------------------------
100//--------------------------------------
101//
102PhysicalZone::PhysicalZone()
103{
104   mNetFlags.set(Ghostable | ScopeAlways);
105
106   mTypeMask |= PhysicalZoneObjectType;
107
108   mVelocityMod = 1.0f;
109   mGravityMod  = 1.0f;
110   mAppliedForce.set(0, 0, 0);
111
112   mConvexList = new Convex;
113   mActive = true;
114   force_type = VECTOR;
115   force_mag = 0.0f;
116   orient_force = false;
117   fade_amt = 1.0f;
118}
119
120PhysicalZone::~PhysicalZone()
121{
122   delete mConvexList;
123   mConvexList = NULL;
124}
125
126
127ImplementEnumType( PhysicalZone_ForceType, "Possible physical zone force types.\n" "@ingroup PhysicalZone\n\n" )
128   { PhysicalZone::VECTOR,          "vector",        "..." },
129   { PhysicalZone::SPHERICAL,       "spherical",     "..." },
130   { PhysicalZone::CYLINDRICAL,     "cylindrical",   "..." },
131   // aliases
132   { PhysicalZone::SPHERICAL,       "sphere",        "..." },
133   { PhysicalZone::CYLINDRICAL,     "cylinder",      "..." },
134EndImplementEnumType;
135
136//--------------------------------------------------------------------------
137void PhysicalZone::consoleInit()
138{
139   Con::addVariable( "$PhysicalZone::renderZones", TypeBool, &smRenderPZones, "If true, a box will render around the location of all PhysicalZones.\n"
140      "@ingroup EnviroMisc\n");
141}
142
143void PhysicalZone::initPersistFields()
144{
145   addGroup("Misc");
146   addField("velocityMod",  TypeF32,               Offset(mVelocityMod,  PhysicalZone), "Multiply velocity of objects entering zone by this value every tick.");
147   addField("gravityMod",   TypeF32,               Offset(mGravityMod,   PhysicalZone), "Gravity in PhysicalZone. Multiplies against standard gravity.");
148   addField("appliedForce", TypePoint3F,           Offset(mAppliedForce, PhysicalZone), "Three-element floating point value representing forces in three axes to apply to objects entering PhysicalZone.");
149   addField("polyhedron",   TypeTriggerPolyhedron, Offset(mPolyhedron,   PhysicalZone),
150      "The polyhedron type is really a quadrilateral and consists of a corner"
151      "point followed by three vectors representing the edges extending from the corner." );
152   endGroup("Misc");
153
154   addGroup("AFX");
155   addField("forceType", TYPEID<PhysicalZone::ForceType>(), Offset(force_type, PhysicalZone));
156   addField("orientForce", TypeBool, Offset(orient_force, PhysicalZone));
157   endGroup("AFX");
158   Parent::initPersistFields();
159}
160
161//--------------------------------------------------------------------------
162bool PhysicalZone::onAdd()
163{
164   if(!Parent::onAdd())
165      return false;
166
167   if (mVelocityMod < -40.0f || mVelocityMod > 40.0f) {
168      Con::errorf("PhysicalZone: velocity mod out of range.  [-40, 40]");
169      mVelocityMod = mVelocityMod < -40.0f ? -40.0f : 40.0f;
170   }
171   if (mGravityMod < -40.0f || mGravityMod > 40.0f) {
172      Con::errorf("PhysicalZone: GravityMod out of range.  [-40, 40]");
173      mGravityMod = mGravityMod < -40.0f ? -40.0f : 40.0f;
174   }
175   static const char* coordString[] = { "x", "y", "z" };
176   F32* p = mAppliedForce;
177   for (U32 i = 0; i < 3; i++) {
178      if (p[i] < -40000.0f || p[i] > 40000.0f) {
179         Con::errorf("PhysicalZone: applied force: %s out of range.  [-40000, 40000]", coordString[i]);
180         p[i] = p[i] < -40000.0f ? -40000.0f : 40000.0f;
181      }
182   }
183
184   Polyhedron temp = mPolyhedron;
185   setPolyhedron(temp);
186
187   switch (force_type)
188   {
189   case SPHERICAL:
190      force_mag = mAppliedForce.magnitudeSafe();
191      break;
192   case CYLINDRICAL:
193      {
194         Point3F force_vec = mAppliedForce;
195         force_vec.z = 0.0;
196         force_mag = force_vec.magnitudeSafe();
197      }
198      break;
199   }
200   addToScene();
201
202   return true;
203}
204
205
206void PhysicalZone::onRemove()
207{
208   mConvexList->nukeList();
209
210   removeFromScene();
211   Parent::onRemove();
212}
213
214void PhysicalZone::inspectPostApply()
215{
216   Parent::inspectPostApply();
217
218   setPolyhedron(mPolyhedron);
219   setMaskBits(PolyhedronMask | MoveMask | SettingsMask | FadeMask);
220}
221
222//------------------------------------------------------------------------------
223void PhysicalZone::setTransform(const MatrixF & mat)
224{
225   Parent::setTransform(mat);
226
227      MatrixF base(true);
228      base.scale(Point3F(1.0/<a href="/coding/class/classsceneobject/#classsceneobject_1abf78914dea349b0201b66591567c6d91">mObjScale</a>.x,
229                         1.0/<a href="/coding/class/classsceneobject/#classsceneobject_1abf78914dea349b0201b66591567c6d91">mObjScale</a>.y,
230                         1.0/<a href="/coding/class/classsceneobject/#classsceneobject_1abf78914dea349b0201b66591567c6d91">mObjScale</a>.z));
231      base.mul(mWorldToObj);
232      mClippedList.setBaseTransform(base);
233
234   if (isServerObject())
235      setMaskBits(MoveMask);
236}
237
238
239void PhysicalZone::prepRenderImage( SceneRenderState *state )
240{
241   // only render if selected or render flag is set
242   if ( !smRenderPZones && !isSelected() )
243      return;
244
245   ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
246   ri->renderDelegate.bind( this, &PhysicalZone::renderObject );
247   ri->type = RenderPassManager::RIT_Editor;
248   ri->defaultKey = 0;
249   ri->defaultKey2 = 0;
250   state->getRenderPass()->addInst( ri );
251}
252
253
254void PhysicalZone::renderObject(ObjectRenderInst *ri,
255   SceneRenderState *state,
256   BaseMatInstance *overrideMat)
257{
258   if (overrideMat)
259      return;
260 
261   GFXStateBlockDesc desc;
262   desc.setZReadWrite(true, false);
263   desc.setBlend(true);
264   desc.setCullMode(GFXCullNone);
265 
266   GFXTransformSaver saver;
267 
268   GFXDrawUtil *drawer = GFX->getDrawUtil();
269 
270   Point3F start = getBoxCenter();
271   Box3F obb = mObjBox; //object bounding box 
272
273   F32 baseForce = 10000; //roughly the ammount of force needed to push a player back as it walks into a zone. (used for visual scaling)
274
275   Point3F forceDir = getForce(&start);
276   F32 forceLen = forceDir.len()/ baseForce;
277   forceDir.normalizeSafe();
278   ColorI guideCol = LinearColorF(mFabs(forceDir.x), mFabs(forceDir.y), mFabs(forceDir.z), 0.125).toColorI();
279
280   if (force_type == VECTOR)
281   {
282      Point3F endPos = start + (forceDir * mMax(forceLen,0.75f));
283      drawer->drawArrow(desc, start, endPos, guideCol, 0.05f);
284   }
285
286   MatrixF mat = getRenderTransform();
287   mat.scale(getScale());
288 
289   GFX->multWorld(mat);
290   start = obb.getCenter();
291 
292   if (force_type == VECTOR)
293   {
294      drawer->drawPolyhedron(desc, mPolyhedron, ColorI(0, 255, 0, 45));
295   }
296   else if (force_type == SPHERICAL)
297   {
298      F32 rad = obb.getBoundingSphere().radius/ 2;
299      drawer->drawSphere(desc, rad, start, ColorI(0, 255, 0, 45));
300
301     rad = (rad + (mAppliedForce.most() / baseForce))/2;
302     desc.setFillModeWireframe();
303     drawer->drawSphere(desc, rad, start, ColorI(0, 0, 255, 255));
304   }
305   else
306   {
307      Point3F bottomPos = start;
308      bottomPos.z -= obb.len_z() / 2;
309 
310      Point3F topPos = start;
311      topPos.z += obb.len_z() / 2;
312     F32 rad = obb.len_x() / 2;
313      drawer->drawCylinder(desc, bottomPos, topPos, rad, ColorI(0, 255, 0, 45));
314
315     Point3F force_vec = mAppliedForce; //raw relative-applied force here as oposed to derived
316     F32 hieght = (force_vec.z / baseForce);
317
318     if (force_vec.z<0)
319        bottomPos.z = (bottomPos.z + hieght)/2;
320     else
321        topPos.z = (topPos.z + hieght) / 2;
322
323     if (force_vec.x > force_vec.y)
324        rad = (rad + (force_vec.x / baseForce)) / 2;
325     else
326        rad = (rad + (force_vec.y / baseForce)) / 2;
327
328
329     desc.setFillModeWireframe();
330     drawer->drawCylinder(desc, bottomPos, topPos, rad, guideCol);
331   }
332 
333   desc.setFillModeWireframe();
334   drawer->drawPolyhedron(desc, mPolyhedron, ColorI::BLACK);
335}
336
337//--------------------------------------------------------------------------
338U32 PhysicalZone::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
339{
340   U32 i;
341   U32 retMask = Parent::packUpdate(con, mask, stream);
342
343   if (stream->writeFlag(mask & PolyhedronMask)) 
344   {
345      // Write the polyhedron
346      stream->write(mPolyhedron.mPointList.size());
347      for (i = 0; i < mPolyhedron.mPointList.size(); i++)
348         mathWrite(*stream, mPolyhedron.mPointList[i]);
349
350      stream->write(mPolyhedron.mPlaneList.size());
351      for (i = 0; i < mPolyhedron.mPlaneList.size(); i++)
352         mathWrite(*stream, mPolyhedron.mPlaneList[i]);
353
354      stream->write(mPolyhedron.mEdgeList.size());
355      for (i = 0; i < mPolyhedron.mEdgeList.size(); i++) {
356         const Polyhedron::Edge& rEdge = mPolyhedron.mEdgeList[i];
357
358         stream->write(rEdge.face[0]);
359         stream->write(rEdge.face[1]);
360         stream->write(rEdge.vertex[0]);
361         stream->write(rEdge.vertex[1]);
362      }
363   }
364
365   if (stream->writeFlag(mask & MoveMask))
366   {
367      stream->writeAffineTransform(mObjToWorld);
368      mathWrite(*stream, mObjScale);
369   }
370
371   if (stream->writeFlag(mask & SettingsMask))
372   {
373      stream->write(mVelocityMod);
374      stream->write(mGravityMod);
375      mathWrite(*stream, mAppliedForce);
376      stream->writeInt(force_type, FORCE_TYPE_BITS);
377      stream->writeFlag(orient_force);
378   }
379
380   if (stream->writeFlag(mask & FadeMask))
381   {
382      U8 fade_byte = (U8)(fade_amt*255.0f);
383      stream->write(fade_byte);
384   }
385
386   stream->writeFlag(mActive);
387
388   return retMask;
389}
390
391void PhysicalZone::unpackUpdate(NetConnection* con, BitStream* stream)
392{
393   Parent::unpackUpdate(con, stream);
394
395   bool new_ph = false;
396   if (stream->readFlag()) // PolyhedronMask
397   {
398      U32 i, size;
399      Polyhedron tempPH;
400
401      // Read the polyhedron
402      stream->read(&size);
403      tempPH.mPointList.setSize(size);
404      for (i = 0; i < tempPH.mPointList.size(); i++)
405         mathRead(*stream, &tempPH.mPointList[i]);
406
407      stream->read(&size);
408      tempPH.mPlaneList.setSize(size);
409      for (i = 0; i < tempPH.mPlaneList.size(); i++)
410         mathRead(*stream, &tempPH.mPlaneList[i]);
411
412      stream->read(&size);
413      tempPH.mEdgeList.setSize(size);
414      for (i = 0; i < tempPH.mEdgeList.size(); i++) {
415         Polyhedron::Edge& rEdge = tempPH.mEdgeList[i];
416
417         stream->read(&rEdge.face[0]);
418         stream->read(&rEdge.face[1]);
419         stream->read(&rEdge.vertex[0]);
420         stream->read(&rEdge.vertex[1]);
421      }
422
423      setPolyhedron(tempPH);
424      new_ph = true;
425   }
426
427   if (stream->readFlag()) // MoveMask
428   {
429      MatrixF temp;
430      stream->readAffineTransform(&temp);
431
432      Point3F tempScale;
433      mathRead(*stream, &tempScale);
434
435      //if (!new_ph)
436      //{
437      //  Polyhedron rPolyhedron = mPolyhedron;
438      //  setPolyhedron(rPolyhedron);
439      //}
440      setScale(tempScale);
441      setTransform(temp);
442   }
443
444   if (stream->readFlag()) //SettingsMask
445   {
446      stream->read(&mVelocityMod);
447      stream->read(&mGravityMod);
448      mathRead(*stream, &mAppliedForce);
449      force_type = stream->readInt(FORCE_TYPE_BITS); // AFX
450      orient_force = stream->readFlag(); // AFX
451   }
452
453   if (stream->readFlag()) //FadeMask
454   {
455      U8 fade_byte;
456      stream->read(&fade_byte);
457      fade_amt = ((F32)fade_byte)/255.0f;
458   }
459   else
460      fade_amt = 1.0f;
461
462   mActive = stream->readFlag();
463}
464
465
466//--------------------------------------------------------------------------
467void PhysicalZone::setPolyhedron(const Polyhedron& rPolyhedron)
468{
469   mPolyhedron = rPolyhedron;
470
471   if (mPolyhedron.mPointList.size() != 0) {
472      mObjBox.minExtents.set(1e10, 1e10, 1e10);
473      mObjBox.maxExtents.set(-1e10, -1e10, -1e10);
474      for (U32 i = 0; i < mPolyhedron.mPointList.size(); i++) {
475         mObjBox.minExtents.setMin(mPolyhedron.mPointList[i]);
476         mObjBox.maxExtents.setMax(mPolyhedron.mPointList[i]);
477      }
478   } else {
479      mObjBox.minExtents.set(-0.5, -0.5, -0.5);
480      mObjBox.maxExtents.set( 0.5,  0.5,  0.5);
481   }
482
483   MatrixF xform = getTransform();
484   setTransform(xform);
485
486   mClippedList.clear();
487   mClippedList.mPlaneList = mPolyhedron.mPlaneList;
488
489   MatrixF base(true);
490   base.scale(Point3F(1.0/<a href="/coding/class/classsceneobject/#classsceneobject_1abf78914dea349b0201b66591567c6d91">mObjScale</a>.x,
491                      1.0/<a href="/coding/class/classsceneobject/#classsceneobject_1abf78914dea349b0201b66591567c6d91">mObjScale</a>.y,
492                      1.0/<a href="/coding/class/classsceneobject/#classsceneobject_1abf78914dea349b0201b66591567c6d91">mObjScale</a>.z));
493   base.mul(mWorldToObj);
494
495   mClippedList.setBaseTransform(base);
496}
497
498
499//--------------------------------------------------------------------------
500void PhysicalZone::buildConvex(const Box3F& box, Convex* convex)
501{
502   // These should really come out of a pool
503   mConvexList->collectGarbage();
504
505   Box3F realBox = box;
506   mWorldToObj.mul(realBox);
507   realBox.minExtents.convolveInverse(mObjScale);
508   realBox.maxExtents.convolveInverse(mObjScale);
509
510   if (realBox.isOverlapped(getObjBox()) == false)
511      return;
512
513   // Just return a box convex for the entire shape...
514   Convex* cc = 0;
515   CollisionWorkingList& wl = convex->getWorkingList();
516   for (CollisionWorkingList* itr = wl.wLink.mNext; itr != &wl; itr = itr->wLink.mNext) {
517      if (itr->mConvex->getType() == BoxConvexType &&
518          itr->mConvex->getObject() == this) {
519         cc = itr->mConvex;
520         break;
521      }
522   }
523   if (cc)
524      return;
525
526   // Create a new convex.
527   BoxConvex* cp = new BoxConvex;
528   mConvexList->registerObject(cp);
529   convex->addToWorkingList(cp);
530   cp->init(this);
531
532   mObjBox.getCenter(&cp->mCenter);
533   cp->mSize.x = mObjBox.len_x() / 2.0f;
534   cp->mSize.y = mObjBox.len_y() / 2.0f;
535   cp->mSize.z = mObjBox.len_z() / 2.0f;
536}
537
538bool PhysicalZone::testObject(SceneObject* enter)
539{
540   // TODO: This doesn't look like it's testing against the polyhedron at
541   // all.  And whats the point of building a convex if no collision methods
542   // are implemented?
543
544   if (mPolyhedron.mPointList.size() == 0)
545      return false;
546
547   mClippedList.clear();
548
549   SphereF sphere;
550   sphere.center = (mWorldBox.minExtents + mWorldBox.maxExtents) * 0.5;
551   VectorF bv = mWorldBox.maxExtents - sphere.center;
552   sphere.radius = bv.len();
553
554   enter->buildPolyList(PLC_Collision, &mClippedList, mWorldBox, sphere);
555   return mClippedList.isEmpty() == false;
556}
557
558bool PhysicalZone::testBox( const Box3F &box ) const
559{
560   return mWorldBox.isOverlapped( box );
561}
562
563void PhysicalZone::activate()
564{
565   AssertFatal(isServerObject(), "Client objects not allowed in ForceFieldInstance::open()");
566
567   if (mActive != true)
568      setMaskBits(ActiveMask);
569   mActive = true;
570}
571
572void PhysicalZone::deactivate()
573{
574   AssertFatal(isServerObject(), "Client objects not allowed in ForceFieldInstance::close()");
575
576   if (mActive != false)
577      setMaskBits(ActiveMask);
578   mActive = false;
579}
580
581void PhysicalZone::onStaticModified(const char* slotName, const char*newValue)
582{
583   if (dStricmp(slotName, "appliedForce") == 0 || dStricmp(slotName, "forceType") == 0)
584   {
585      switch (force_type)
586      {
587      case SPHERICAL:
588         force_mag = mAppliedForce.magnitudeSafe();
589         break;
590      case CYLINDRICAL:
591         {
592            Point3F force_vec = mAppliedForce;
593            force_vec.z = 0.0;
594            force_mag = force_vec.magnitudeSafe();
595         }
596         break;
597      }
598   }
599}
600
601const Point3F& PhysicalZone::getForce(const Point3F* center) const 
602{ 
603   static Point3F force_vec;
604
605   if (force_type == VECTOR)
606   {
607      if (orient_force)
608      {
609         getTransform().mulV(mAppliedForce, &force_vec);
610         force_vec *= fade_amt;
611         return force_vec; 
612      }
613      force_vec = mAppliedForce;
614      force_vec *= fade_amt;
615      return force_vec;
616   }
617
618   if (!center)
619   {
620      force_vec.zero();
621      return force_vec; 
622   }
623
624   if (force_type == SPHERICAL)
625   {
626      force_vec = *center - getPosition();
627      force_vec.normalizeSafe();
628      force_vec *= force_mag*fade_amt;
629      return force_vec;
630   }
631
632   if (orient_force)
633   {
634      force_vec = *center - getPosition();
635      getWorldTransform().mulV(force_vec);
636      force_vec.z = 0.0f;
637      force_vec.normalizeSafe();
638      force_vec *= force_mag;
639      force_vec.z = mAppliedForce.z;
640      getTransform().mulV(force_vec);
641      force_vec *= fade_amt;
642      return force_vec;
643   }
644
645   force_vec = *center - getPosition();
646   force_vec.z = 0.0f;
647   force_vec.normalizeSafe();
648   force_vec *= force_mag;
649   force_vec *= fade_amt;
650   return force_vec;
651}
652
653bool PhysicalZone::isExcludedObject(SceneObject* obj) const
654{
655   for (S32 i = 0; i < excluded_objects.size(); i++)
656      if (excluded_objects[i] == obj)
657         return true;
658
659   return false;
660}
661
662void PhysicalZone::registerExcludedObject(SceneObject* obj)
663{
664   if (isExcludedObject(obj))
665      return;
666
667   excluded_objects.push_back(obj);
668   setMaskBits(FadeMask);
669}
670
671void PhysicalZone::unregisterExcludedObject(SceneObject* obj)
672{
673   for (S32 i = 0; i < excluded_objects.size(); i++)
674      if (excluded_objects[i] == obj)
675      {
676         excluded_objects.erase(i);
677         setMaskBits(FadeMask);
678         return;
679      }
680}
681
682