Spinning Topp Logo BlackTopp Studios
inc
fieldofforce.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 _fieldofforce_cpp
41 #define _fieldofforce_cpp
42 
43 #include "fieldofforce.h"
44 
45 #include "Physics/rigidproxy.h"
46 #include "Physics/ghostproxy.h"
47 
48 #include "serialization.h"
49 #include "exception.h"
50 
51 namespace Mezzanine
52 {
53  ///////////////////////////////////////////////////////////////////////////////
54  // FieldOfForce Methods
55 
57  AreaEffect(TheWorld),
58  AttenSource(Vector3(0,0,0)),
59  Direction(Vector3(0,1,0)),
60  AttenAmount(0),
61  Strength(0),
62  AttenStyle(Mezzanine::Att_None)
63  { }
64 
65  FieldOfForce::FieldOfForce(const String& Name, World* TheWorld) :
66  AreaEffect(Name,TheWorld),
67  AttenSource(Vector3(0,0,0)),
68  Direction(Vector3(0,1,0)),
69  AttenAmount(0),
70  Strength(0),
71  AttenStyle(Mezzanine::Att_None)
72  { }
73 
75  AreaEffect(Name,Shape,TheWorld),
76  AttenSource(Vector3(0,0,0)),
77  Direction(Vector3(0,1,0)),
78  AttenAmount(0),
79  Strength(0),
80  AttenStyle(Mezzanine::Att_None)
81  { }
82 
83  FieldOfForce::FieldOfForce(const XML::Node& SelfRoot, World* TheWorld) :
84  AreaEffect(TheWorld),
85  AttenSource(Vector3(0,0,0)),
86  Direction(Vector3(0,1,0)),
87  AttenAmount(0),
88  Strength(0),
89  AttenStyle(Mezzanine::Att_None)
90  { this->ProtoDeSerialize(SelfRoot); }
91 
93  { }
94 
95  ///////////////////////////////////////////////////////////////////////////////
96  // Utility
97 
99  { return Mezzanine::WO_AreaEffectFieldOfForce; }
100 
102  {
103  /// @todo This currently will apply this fields force uniformly to all rigid proxies contained in a WorldObject.
104  /// Instead this should perhaps apply only to the ones in the field, or perhaps apply force based on the proxy position
105  /// rather than the WorldObject position to get more interesting results.
106  /// @todo Update to allow the application of force to soft proxies.
107 
108  if(0 == this->Strength)
109  return;
110  if( !this->OverlappingObjects.empty() ) {
111  Vector3 ObjectLoc;
112  //Real Distance, AppliedStrength, InvMass;
113  Real Distance, AppliedStrength;
114  for( ObjectIterator ObjIt = this->OverlappingObjects.begin() ; ObjIt != this->OverlappingObjects.end() ; ObjIt++ )
115  {
116  ProxyContainer RigidProxies;
117  (*ObjIt)->GetProxies(Mezzanine::PT_Physics_RigidProxy,RigidProxies);
118  if( RigidProxies.empty() )
119  continue;
120 
121  ObjectLoc = (*ObjIt)->GetLocation();
122  switch(this->AttenStyle)
123  {
125  {
126  Distance = ObjectLoc.Distance(this->AttenSource);
127  AppliedStrength = this->Strength - (this->AttenAmount * Distance);
128  break;
129  }
131  {
132  Distance = ObjectLoc.Distance(this->AttenSource);
133  AppliedStrength = this->Strength - (this->AttenAmount * (Distance * Distance));
134  break;
135  }
136  case Mezzanine::Att_None:
137  {
138  AppliedStrength = this->Strength;
139  break;
140  }
141  }
142 
143  // Collect necessary data
144  //InvMass = (*ObjIt)->GetBulletObject()->getInvMass();
145  //if(0 != InvMass)
146  // AppliedStrength *= (1 / (*ObjIt)->GetBulletObject()->getInvMass());
147  //else
148  // AppliedStrength = 0;
149  if(0 > AppliedStrength)
150  AppliedStrength = 0;
151 
152  //Apply the Force
153  for( ProxyIterator ProxIt = RigidProxies.begin() ; ProxIt != RigidProxies.end() ; ++ProxIt )
154  {
155  Physics::RigidProxy* RigProx = static_cast<Physics::RigidProxy*>( *ProxIt );
156  RigProx->ApplyForce( Direction * AppliedStrength );
157  }
158  }
159  }
160  }
161 
162  ///////////////////////////////////////////////////////////////////////////////
163  // FieldOfForce Properties
164 
165  void FieldOfForce::SetFieldStrength(const Real FieldStrength)
166  { this->Strength = FieldStrength; }
167 
169  { return this->Strength; }
170 
171  void FieldOfForce::SetDirectionOfForce(const Vector3& ForceDirection)
172  { this->Direction = ForceDirection; }
173 
175  { return this->Direction; }
176 
177  void FieldOfForce::SetAttenuation(const Real Amount, const Mezzanine::AttenuationStyle Style, const Vector3& Source)
178  {
179  this->AttenAmount = Amount;
180  this->AttenStyle = Style;
181  this->AttenSource = Source;
182  }
183 
185  { this->AttenStyle = Style; }
186 
188  { return this->AttenStyle; }
189 
191  { this->AttenAmount = Amount; }
192 
194  { return this->AttenAmount; }
195 
197  { this->AttenSource = Source; }
198 
200  { return this->AttenSource; }
201 
202  ///////////////////////////////////////////////////////////////////////////////
203  // Serialization
204 
206  {
207  this->AreaEffect::ProtoSerializeProperties(SelfRoot);
208 
209  XML::Node PropertiesNode = SelfRoot.AppendChild( FieldOfForce::GetSerializableName() + "Properties" );
210 
211  if( PropertiesNode.AppendAttribute("Version").SetValue("1") &&
212  PropertiesNode.AppendAttribute("AttenAmount").SetValue( this->GetAttenuationAmount() ) &&
213  PropertiesNode.AppendAttribute("AttenStyle").SetValue( this->GetAttenuationStyle() ) &&
214  PropertiesNode.AppendAttribute("Strength").SetValue( this->GetFieldStrength() ) )
215  {
216  XML::Node AttenSourceNode = PropertiesNode.AppendChild("AttenSource");
217  this->GetAttenuationSource().ProtoSerialize( AttenSourceNode );
218  XML::Node DirectionNode = PropertiesNode.AppendChild("Direction");
219  this->GetDirectionOfForce().ProtoSerialize( DirectionNode );
220 
221  return;
222  }else{
223  SerializeError("Create XML Attribute Values",FieldOfForce::GetSerializableName() + "Properties",true);
224  }
225  }
226 
228  {
230 
231  XML::Attribute CurrAttrib;
232  XML::Node PropertiesNode = SelfRoot.GetChild( FieldOfForce::GetSerializableName() + "Properties" );
233 
234  if( !PropertiesNode.Empty() ) {
235  if(PropertiesNode.GetAttribute("Version").AsInt() == 1) {
236  CurrAttrib = PropertiesNode.GetAttribute("AttenAmount");
237  if( !CurrAttrib.Empty() )
238  this->SetAttenuationAmount( CurrAttrib.AsReal() );
239 
240  CurrAttrib = PropertiesNode.GetAttribute("AttenStyle");
241  if( !CurrAttrib.Empty() )
242  this->SetAttenuationStyle( static_cast<Mezzanine::AttenuationStyle>( CurrAttrib.AsWhole() ) );
243 
244  CurrAttrib = PropertiesNode.GetAttribute("Strength");
245  if( !CurrAttrib.Empty() )
246  this->SetFieldStrength( CurrAttrib.AsReal() );
247 
248  XML::Node AttenSourceNode = PropertiesNode.GetChild("AttenSource").GetFirstChild();
249  if( !AttenSourceNode.Empty() ) {
250  Vector3 Source(AttenSourceNode);
251  this->SetAttenuationSource(Source);
252  }
253 
254  XML::Node DirectionNode = PropertiesNode.GetChild("Direction").GetFirstChild();
255  if( !DirectionNode.Empty() ) {
256  Vector3 Dir(DirectionNode);
257  this->SetDirectionOfForce(Dir);
258  }
259  }else{
260  MEZZ_EXCEPTION(ExceptionBase::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for " + (FieldOfForce::GetSerializableName() + "Properties" ) + ": Not Version 1.");
261  }
262  }else{
263  MEZZ_EXCEPTION(ExceptionBase::II_IDENTITY_NOT_FOUND_EXCEPTION,FieldOfForce::GetSerializableName() + "Properties" + " was not found in the provided XML node, which was expected.");
264  }
265  }
266 
269 
271  { return "FieldOfForce"; }
272 
273  ///////////////////////////////////////////////////////////////////////////////
274  // FieldOfForceFactory Methods
275 
277  { }
278 
280  { }
281 
284 
286  { return new FieldOfForce(Name,TheWorld); }
287 
289  { return new FieldOfForce(Name,AEShape,TheWorld); }
290 
292  { return static_cast<FieldOfForce*>( this->CreateAreaEffect(XMLNode,TheWorld) ); }
293 
295  { return new FieldOfForce(Name,TheWorld); }
296 
298  { return new FieldOfForce(XMLNode,TheWorld); }
299 
301  { delete ToBeDestroyed; }
302 }//Mezzanine
303 
304 #endif
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.
A light-weight handle for manipulating attributes in DOM tree.
Definition: attribute.h:74
virtual Mezzanine::AttenuationStyle GetAttenuationStyle() const
Gets the method of attenuation of force over a distance.
virtual void ApplyForce(const Vector3 &Force)
Push/Apply force to an proxy.
Definition: rigidproxy.cpp:210
virtual void ApplyEffect()
FieldOfForceFactory()
Class constructor.
virtual Vector3 GetDirectionOfForce() const
Gets the currenly set direction force is to be applied.
virtual void ProtoDeSerializeProperties(const XML::Node &SelfRoot)
Take the data stored in an XML Node and overwrite the properties of this object with it...
virtual String GetTypeName() const
Real Strength
The amount of force exerted on other objects.
Definition: fieldofforce.h:70
Quadratic/Exponential Attentuation, similar to real gravity, it tapers of more the further from the c...
Definition: enumerations.h:60
virtual AreaEffect * CreateAreaEffect(const String &Name, World *TheWorld, const NameValuePairMap &Params)
virtual ~FieldOfForceFactory()
Class destructor.
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
Node GetFirstChild() const
Get the first child Node of this Node.
#define MEZZ_EXCEPTION(num, desc)
An easy way to throw exceptions with rich information.
Definition: exception.h:3048
Thrown when a version is accessed/parsed/required and it cannot work correctly or is missing...
Definition: exception.h:112
virtual void ProtoSerializeProperties(XML::Node &SelfRoot) const
Convert the properties of this class to an XML::Node ready for serialization.
ObjectContainer OverlappingObjects
Container for actors within the field area.
Definition: areaeffect.h:77
No Attentuation, Equal strength through.
Definition: enumerations.h:58
virtual Vector3 GetAttenuationSource() const
Gets the source of the force for calculating attenuation.
bool Empty() const
Is this storing anything at all?
This implements the exception hiearchy for Mezzanine.
Mezzanine::AttenuationStyle AttenStyle
How gravity weakens over distance, if at all.
Definition: fieldofforce.h:73
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
This is field that applies force in a direction, and doesn't tamper with gravity. ...
Definition: fieldofforce.h:56
virtual void ProtoSerializeProperties(XML::Node &SelfRoot) const
Convert the properties of this class to an XML::Node ready for serialization.
Definition: areaeffect.cpp:279
virtual Mezzanine::WorldObjectType GetType() const
Gets the type of the object instance.
Whole AsWhole(Whole def=0) const
Attempts to convert the value of the attribute to a Whole and returns the results.
A light-weight handle for manipulating nodes in DOM tree.
Definition: node.h:89
virtual void SetFieldStrength(const Real FieldStrength)
Sets the strenth of the field.
virtual FieldOfForce * CreateFieldOfForce(const String &Name, World *TheWorld)
Creates a FieldOfForce object.
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
virtual void DestroyAreaEffect(AreaEffect *ToBeDestroyed)
bool Empty() const
Is this storing anything at all?
Real AsReal(Real def=0) const
Attempts to convert the value of the attribute to a Real and returns the results. ...
virtual Real GetAttenuationAmount() const
Gets the amount of force that is attenuated over distance.
static String GetSerializableName()
Get the name of the the XML tag the proxy class will leave behind as its instances are serialized...
virtual Real GetFieldStrength() const
Gets the strength of the field.
This is a proxy from which rigid body proxys are handled.
Definition: rigidproxy.h:102
virtual ~FieldOfForce()
Class destructor.
virtual void SetDirectionOfForce(const Vector3 &ForceDirection)
Sets the direction force is to be applied within this field.
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
Vector3 Direction
The direction the force is applied.
Definition: fieldofforce.h:64
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
virtual void SetAttenuationAmount(const Real Amount)
Sets the amount of force that is attenuated over distance.
This class represents a world for objects to interact within.
Definition: world.h:74
virtual void SetAttenuation(const Real Amount, const Mezzanine::AttenuationStyle Style, const Vector3 &Source)
Sets the attenuation for this field.
virtual String GetDerivedSerializableName() const
Gets the most derived serializable name of this WorldObject.
virtual void SetAttenuationSource(const Vector3 &Source)
Sets the source of the force for calculating attenuation.
FieldOfForce(World *TheWorld)
Blank constructor.
Vector3 AttenSource
The user defined source if enabled.
Definition: fieldofforce.h:61
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.
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
std::string String
A datatype used to a series of characters.
Definition: datatypes.h:159
Real AttenAmount
How much the Gravity weakens over distance.
Definition: fieldofforce.h:67
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 void SetAttenuationStyle(const Mezzanine::AttenuationStyle Style)
Sets the method of attenuation of force over a distance.
void ProtoSerialize(XML::Node &CurrentRoot) const
Convert this class to an XML::Node ready for serialization.
Definition: vector3.cpp:588
Node GetChild(const Char8 *Name) const
Attempt to get a child Node with a given name.