Spinning Topp Logo BlackTopp Studios
inc
gravitywell.cpp
1 // © Copyright 2010 - 2016 BlackTopp Studios Inc.
2 /* This file is part of The Mezzanine Engine.
3 
4  The Mezzanine Engine is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  The Mezzanine Engine is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* The original authors have included a copy of the license specified above in the
18  'Docs' folder. See 'gpl.txt'
19 */
20 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
21  Build professional software and charge for their product.
22 
23  However there are some practical restrictions, so if your project involves
24  any of the following you should contact us and we will try to work something
25  out:
26  - DRM or Copy Protection of any kind(except Copyrights)
27  - Software Patents You Do Not Wish to Freely License
28  - Any Kind of Linking to Non-GPL licensed Works
29  - Are Currently In Violation of Another Copyright Holder's GPL License
30  - If You want to change our code and not add a few hundred MB of stuff to
31  your distribution
32 
33  These and other limitations could cause serious legal problems if you ignore
34  them, so it is best to simply contact us or the Free Software Foundation, if
35  you have any questions.
36 
37  Joseph Toppi - toppij@gmail.com
38  John Blackwood - makoenergy02@gmail.com
39 */
40 #ifndef _gravitywell_cpp
41 #define _gravitywell_cpp
42 
43 #include "gravitywell.h"
44 
45 #include "Physics/rigidproxy.h"
46 #include "Physics/ghostproxy.h"
47 #include "Physics/physicsmanager.h"
48 
49 #include "entresol.h"
50 #include "world.h"
51 #include "serialization.h"
52 #include "exception.h"
53 #include "stringtool.h"
54 
55 namespace Mezzanine
56 {
58  AreaEffect(TheWorld),
59  AttenAmount(0),
60  Strength(0),
61  AttenStyle(Mezzanine::Att_None),
62  AllowWorldGrav(true)
63  { }
64 
65  GravityWell::GravityWell(const String& Name, World* TheWorld) :
66  AreaEffect(Name,TheWorld),
67  AttenAmount(0),
68  Strength(0),
69  AttenStyle(Mezzanine::Att_None),
70  AllowWorldGrav(true)
71  { }
72 
74  AreaEffect(Name,Shape,TheWorld),
75  AttenAmount(0),
76  Strength(0),
77  AttenStyle(Mezzanine::Att_None),
78  AllowWorldGrav(true)
79  { }
80 
81  GravityWell::GravityWell(const XML::Node& SelfRoot, World* TheWorld) :
82  AreaEffect(TheWorld),
83  AttenAmount(0),
84  Strength(0),
85  AttenStyle(Mezzanine::Att_None),
86  AllowWorldGrav(true)
87  { this->ProtoDeSerialize(SelfRoot); }
88 
90  { }
91 
92  ///////////////////////////////////////////////////////////////////////////////
93  // Utility
94 
96  { return Mezzanine::WO_AreaEffectGravityWell; }
97 
99  {
100  /// @todo This currently will apply this fields force uniformly to all rigid proxies contained in a WorldObject.
101  /// Instead this should perhaps apply only to the ones in the field, or perhaps apply force based on the proxy position
102  /// rather than the WorldObject position to get more interesting results.
103  /// @todo Update to allow the application of force to soft proxies.
104 
105  if( 0 == this->Strength )
106  return;
107 
108  if( !this->AllowWorldGrav && !this->AddedObjects.empty() )
109  {
110  for( ObjectIterator AddedIt = this->AddedObjects.begin() ; AddedIt != this->AddedObjects.end() ; ++AddedIt )
111  {
112  ProxyContainer RigidProxies;
113  (*AddedIt)->GetProxies(Mezzanine::PT_Physics_RigidProxy,RigidProxies);
114  for( ProxyIterator ProxIt = RigidProxies.begin() ; ProxIt != RigidProxies.end() ; ++ProxIt )
115  {
116  Physics::RigidProxy* RigProx = static_cast<Physics::RigidProxy*>( *ProxIt );
117  RigProx->SetGravity( Vector3(0,0,0) );
118  }
119  }
120  }
121 
122  if( !this->OverlappingObjects.empty() ) {
123  const Vector3 SelfLoc = this->Ghost->GetLocation();
124  Vector3 ObjectLoc, Direction;
125  Real Distance = 0,AppliedStrength = 0;
126 
127  for( ObjectIterator ObjIt = this->OverlappingObjects.begin() ; ObjIt != this->OverlappingObjects.end() ; ObjIt++ )
128  {
129  ProxyContainer RigidProxies;
130  (*ObjIt)->GetProxies(Mezzanine::PT_Physics_RigidProxy,RigidProxies);
131  if( RigidProxies.empty() )
132  continue;
133 
134  Distance = ObjectLoc.Distance(SelfLoc);
135  Direction = (SelfLoc - ObjectLoc) / Distance;
136  switch(this->AttenStyle)
137  {
139  AppliedStrength = Strength - (AttenAmount * Distance);
140  break;
142  AppliedStrength = Strength - (AttenAmount * (Distance * Distance));
143  break;
144  default:
145  AppliedStrength = Strength;
146  break;
147  }
148 
149  //Apply the Force
150  for( ProxyIterator ProxIt = RigidProxies.begin() ; ProxIt != RigidProxies.end() ; ++ProxIt )
151  {
152  Physics::RigidProxy* RigProx = static_cast<Physics::RigidProxy*>( *ProxIt );
153 
154  Real Mass = RigProx->GetMass();
155  if( 0 > AppliedStrength ) {
156  AppliedStrength = 0;
157  }
158 
159  RigProx->ApplyForce( Direction * (AppliedStrength * Mass ) );
160  }
161  }
162  }
163 
164  if( !this->AllowWorldGrav && !this->RemovedObjects.empty() )
165  {
166  const Vector3 WorldGravity = static_cast<Physics::PhysicsManager*>( this->ParentWorld->GetManager(ManagerBase::MT_PhysicsManager) )->GetWorldGravity();
167  for( ObjectIterator RemovedIt = this->RemovedObjects.begin() ; RemovedIt != this->RemovedObjects.end() ; ++RemovedIt )
168  {
169  ProxyContainer RigidProxies;
170  (*RemovedIt)->GetProxies(Mezzanine::PT_Physics_RigidProxy,RigidProxies);
171  for( ProxyIterator ProxIt = RigidProxies.begin() ; ProxIt != RigidProxies.end() ; ++ProxIt )
172  {
173  Physics::RigidProxy* RigProx = static_cast<Physics::RigidProxy*>( *ProxIt );
174  RigProx->SetGravity( WorldGravity );
175  }
176  }
177  }
178  }
179 
180  ///////////////////////////////////////////////////////////////////////////////
181  // GravityWell Properties
182 
183  void GravityWell::SetFieldStrength(const Real FieldStrength)
184  { this->Strength = FieldStrength; }
185 
187  { return this->Strength; }
188 
190  { this->AllowWorldGrav = WorldGravity; }
191 
193  { return this->AllowWorldGrav; }
194 
196  {
197  this->AttenAmount = Amount;
198  this->AttenStyle = Style;
199  }
200 
202  { this->AttenStyle = Style; }
203 
205  { return this->AttenStyle; }
206 
208  { this->AttenAmount = Amount; }
209 
211  { return this->AttenAmount; }
212 
213  ///////////////////////////////////////////////////////////////////////////////
214  // Serialization
215 
217  {
218  this->AreaEffect::ProtoSerializeProperties(SelfRoot);
219 
220  XML::Node PropertiesNode = SelfRoot.AppendChild( GravityWell::GetSerializableName() + "Properties" );
221 
222  if( PropertiesNode.AppendAttribute("Version").SetValue("1") &&
223  PropertiesNode.AppendAttribute("AttenAmount").SetValue( this->GetAttenuationAmount() ) &&
224  PropertiesNode.AppendAttribute("AttenStyle").SetValue( this->GetAttenuationStyle() ) &&
225  PropertiesNode.AppendAttribute("Strength").SetValue( this->GetFieldStrength() ) &&
226  PropertiesNode.AppendAttribute("AllowWorldGravity").SetValue( this->GetAllowWorldGravity() ? "true" : "false" ) )
227  {
228  return;
229  }else{
230  SerializeError("Create XML Attribute Values",GravityWell::GetSerializableName() + "Properties",true);
231  }
232  }
233 
235  {
237 
238  XML::Attribute CurrAttrib;
239  XML::Node PropertiesNode = SelfRoot.GetChild( GravityWell::GetSerializableName() + "Properties" );
240 
241  if( !PropertiesNode.Empty() ) {
242  if(PropertiesNode.GetAttribute("Version").AsInt() == 1) {
243  CurrAttrib = PropertiesNode.GetAttribute("AttenAmount");
244  if( !CurrAttrib.Empty() )
245  this->SetAttenuationAmount( CurrAttrib.AsReal() );
246 
247  CurrAttrib = PropertiesNode.GetAttribute("AttenStyle");
248  if( !CurrAttrib.Empty() )
249  this->SetAttenuationStyle( static_cast<Mezzanine::AttenuationStyle>( CurrAttrib.AsWhole() ) );
250 
251  CurrAttrib = PropertiesNode.GetAttribute("Strength");
252  if( !CurrAttrib.Empty() )
253  this->SetFieldStrength( CurrAttrib.AsReal() );
254 
255  CurrAttrib = PropertiesNode.GetAttribute("AllowWorldGravity");
256  if( !CurrAttrib.Empty() )
258  }else{
259  MEZZ_EXCEPTION(ExceptionBase::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for " + (GravityWell::GetSerializableName() + "Properties" ) + ": Not Version 1.");
260  }
261  }else{
262  MEZZ_EXCEPTION(ExceptionBase::II_IDENTITY_NOT_FOUND_EXCEPTION,GravityWell::GetSerializableName() + "Properties" + " was not found in the provided XML node, which was expected.");
263  }
264  }
265 
268 
270  { return "GravityWell"; }
271 
272  ///////////////////////////////////////////////////////////////////////////////
273  // GravityWellFactory Methods
274 
276  { }
277 
279  { }
280 
283 
285  { return new GravityWell(Name,TheWorld); }
286 
288  { return new GravityWell(Name,AEShape,TheWorld); }
289 
291  { return static_cast<GravityWell*>( this->CreateAreaEffect(XMLNode,TheWorld) ); }
292 
294  { return new GravityWell(Name,TheWorld); }
295 
297  { return new GravityWell(XMLNode,TheWorld); }
298 
300  { delete ToBeDestroyed; }
301 }//Mezzanine
302 
303 #endif
virtual void SetFieldStrength(const Real FieldStrength)
Sets the strenth of the field.
virtual void SetAttenuationAmount(const Real Amount)
Sets the amount of force that is attenuated over distance.
This is the base class for all collision shapes.
Attribute AppendAttribute(const Char8 *Name)
Creates an Attribute and puts it at the end of this Nodes attributes.
WorldManager * GetManager(const Whole ManagerToGet)
This is will find the manager of a given type.
Definition: world.cpp:324
A light-weight handle for manipulating attributes in DOM tree.
Definition: attribute.h:74
virtual void ApplyForce(const Vector3 &Force)
Push/Apply force to an proxy.
Definition: rigidproxy.cpp:210
virtual ~GravityWellFactory()
Class destructor.
ObjectContainer AddedObjects
Container of actors that have been added since last frame.
Definition: areaeffect.h:80
bool Boole
Generally acts a single bit, true or false.
Definition: datatypes.h:173
Quadratic/Exponential Attentuation, similar to real gravity, it tapers of more the further from the c...
Definition: enumerations.h:60
ObjectContainer::iterator ObjectIterator
Iterator type for Object instances stored by this class.
Definition: areaeffect.h:71
Thrown when the requested identity could not be found.
Definition: exception.h:94
#define MEZZ_EXCEPTION(num, desc)
An easy way to throw exceptions with rich information.
Definition: exception.h:3048
Real AttenAmount
how much does the Gravity attenuate.
Definition: gravitywell.h:57
virtual void ProtoSerializeProperties(XML::Node &SelfRoot) const
Convert the properties of this class to an XML::Node ready for serialization.
This is a gravity well implementation of the AreaEffect class.
Definition: gravitywell.h:53
Thrown when a version is accessed/parsed/required and it cannot work correctly or is missing...
Definition: exception.h:112
virtual Vector3 GetLocation() const
Gets this objects current location.
virtual Boole GetAllowWorldGravity() const
Gets whether or not world gravity is is removed for objects inside this field.
virtual String GetDerivedSerializableName() const
Gets the most derived serializable name of this WorldObject.
const Char8 * AsString(const Char8 *def="") const
Attempts to convert the value of the attribute to a String and returns the results.
virtual void SetAllowWorldGravity(Boole WorldGravity)
Sets whether or not world gravity should be removed for objects in this field.
World * ParentWorld
This is the world this object belongs to and will be inserted in/removed from.
Definition: worldobject.h:84
static String GetSerializableName()
Get the name of the the XML tag the proxy class will leave behind as its instances are serialized...
virtual void DestroyAreaEffect(AreaEffect *ToBeDestroyed)
virtual AreaEffect * CreateAreaEffect(const String &Name, World *TheWorld, const NameValuePairMap &Params)
ObjectContainer OverlappingObjects
Container for actors within the field area.
Definition: areaeffect.h:77
virtual Real GetFieldStrength() const
Gets the strength of the field.
No Attentuation, Equal strength through.
Definition: enumerations.h:58
bool Empty() const
Is this storing anything at all?
virtual ~GravityWell()
Class destructor.
Definition: gravitywell.cpp:89
This implements the exception hiearchy for Mezzanine.
virtual String GetTypeName() const
Real Distance(const Vector3 &OtherVec) const
Gets the distance between this and another vector.
Definition: vector3.cpp:449
Linear attentuation, Strength weaker farther from center.
Definition: enumerations.h:59
float Real
A Datatype used to represent a real floating point number.
Definition: datatypes.h:141
The interface for serialization.
std::vector< WorldProxy * > ProxyContainer
Basic container type for WorldProxy storage by this class.
Definition: worldobject.h:64
bool SetValue(const Char8 *rhs)
Set the value of this.
This class is used to define area's in the world that have unique effects.
Definition: areaeffect.h:65
Boole AllowWorldGrav
Should world gravity ne ignored.
Definition: gravitywell.h:63
virtual void ProtoSerializeProperties(XML::Node &SelfRoot) const
Convert the properties of this class to an XML::Node ready for serialization.
Definition: areaeffect.cpp:279
Whole AsWhole(Whole def=0) const
Attempts to convert the value of the attribute to a Whole and returns the results.
Boole ConvertToBool(const String &ToConvert, const Boole Default)
Converts a string into a Boole.
Definition: stringtool.cpp:379
A light-weight handle for manipulating nodes in DOM tree.
Definition: node.h:89
int AsInt(int def=0) const
Attempts to convert the value of the attribute to an int and returns the results. ...
virtual void ProtoDeSerializeProperties(const XML::Node &SelfRoot)
Take the data stored in an XML Node and overwrite the properties of this object with it...
Definition: areaeffect.cpp:300
bool Empty() const
Is this storing anything at all?
virtual Real GetAttenuationAmount() const
Gets the amount force is attenuated over distance.
virtual GravityWell * CreateGravityWell(const String &Name, World *TheWorld)
Creates a GravityWell object.
Real AsReal(Real def=0) const
Attempts to convert the value of the attribute to a Real and returns the results. ...
Physics::GhostProxy * Ghost
A pointer to the ghost powering this AE field.
Definition: areaeffect.h:89
virtual Mezzanine::WorldObjectType GetType() const
Gets the type of the object instance.
Definition: gravitywell.cpp:95
virtual void ProtoDeSerializeProperties(const XML::Node &SelfRoot)
Take the data stored in an XML Node and overwrite the properties of this object with it...
GravityWellFactory()
Class constructor.
This is a proxy from which rigid body proxys are handled.
Definition: rigidproxy.h:102
This is simply a place for storing all the Physics Related functions.
GravityWell(World *TheWorld)
Blank constructor.
Definition: gravitywell.cpp:57
Mezzanine::AttenuationStyle AttenStyle
How does gravity.
Definition: gravitywell.h:61
ProxyContainer::iterator ProxyIterator
Iterator type for WorldProxy instances stored by this class.
Definition: worldobject.h:66
This is used to represent a point in space, or a vector through space.
Definition: vector3.h:77
virtual void ApplyEffect()
Definition: gravitywell.cpp:98
virtual void SetAttenuation(const Real Amount, const Mezzanine::AttenuationStyle Style)
Sets the attenuation for this field.
WorldObjectType
Used by various classes to help identify what class an object is.
Definition: enumerations.h:147
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
This class represents a world for objects to interact within.
Definition: world.h:74
virtual void SetAttenuationStyle(const Mezzanine::AttenuationStyle Style)
Sets the method of attenuation of force over a distance.
virtual void SetGravity(const Vector3 &Gravity)
Sets the gravity for only this proxy.
Definition: rigidproxy.cpp:204
void SerializeError(const String &FailedTo, const String &ClassName, Boole SOrD)
Simply does some string concatenation, then throws an Exception.
virtual void ProtoDeSerialize(const XML::Node &SelfRoot)
Take the data stored in an XML Node and overwrite this object with it.
Node AppendChild(NodeType Type=NodeElement)
Creates a Node and makes it a child of this one.
ObjectContainer RemovedObjects
Container of actors that have been removed since last frame.
Definition: areaeffect.h:83
std::map< String, String > NameValuePairMap
This is a datatype mostly used for describing settings or parameters that can't be declared in advanc...
Definition: datatypes.h:209
Real Strength
The amount of force exerted on other objects.
Definition: gravitywell.h:59
std::string String
A datatype used to a series of characters.
Definition: datatypes.h:159
AttenuationStyle
These values represent the kind of attenuation applied to the field strength over a distance...
Definition: enumerations.h:56
Attribute GetAttribute(const Char8 *Name) const
Attempt to get an Attribute on this Node with a given name.
virtual Mezzanine::AttenuationStyle GetAttenuationStyle() const
Gets the Style of attenuation applied.
Node GetChild(const Char8 *Name) const
Attempt to get a child Node with a given name.
virtual Real GetMass() const
Get the total Mass of the proxy.
Definition: rigidproxy.cpp:180