physicsForce.cpp
Engine/source/T3D/physics/physicsForce.cpp
Public Functions
ConsoleDocClass(PhysicsForce , "@brief Helper object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> gameplay physical <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">forces.\n\n</a>" "%PhysicsForces can be created and \"attached\" to other @link <a href="/coding/class/classphysicsbody/">PhysicsBody</a> PhysicsBodies@endlink " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> attract them <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the position of the PhysicsForce." "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Physics\n</a>" )
DefineEngineMethod(PhysicsForce , attach , void , (Point3F start, Point3F direction, F32 maxDist) , "@brief Attempts <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> associate the <a href="/coding/class/classphysicsforce/">PhysicsForce</a> with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">PhysicsBody.\n\n</a>" "Performs <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> physics ray cast of the provided length and direction. The %<a href="/coding/class/classphysicsforce/">PhysicsForce</a> " "will attach itself <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the first dynamic <a href="/coding/class/classphysicsbody/">PhysicsBody</a> the ray collides with. " "On every tick, the attached body will be attracted towards the position of the %<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">PhysicsForce.\n\n</a>" "A %<a href="/coding/class/classphysicsforce/">PhysicsForce</a> can only be attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> one body at <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">time.\n\n</a>" " @note To determine <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> an %attach was successful, check isAttached() immediately after " "calling this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">function.n\n</a>" )
DefineEngineMethod(PhysicsForce , detach , void , (Point3F force) , (Point3F::Zero) , "@brief Disassociates the <a href="/coding/class/classphysicsforce/">PhysicsForce</a> from any attached <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">PhysicsBody.\n\n</a>" "@param force Optional force <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> apply <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the attached <a href="/coding/class/classphysicsbody/">PhysicsBody</a> " "before <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">detaching.\n\n</a>" "@note Has no effect <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the %<a href="/coding/class/classphysicsforce/">PhysicsForce</a> is not attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">anything.\n\n</a>" )
DefineEngineMethod(PhysicsForce , isAttached , bool , () , "@brief Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the %<a href="/coding/class/classphysicsforce/">PhysicsForce</a> is currently attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> an <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@see <a href="/coding/class/classphysicsforce/#classphysicsforce_1a75a89178a0bcf6cb288b18a3a23170f5">PhysicsForce::attach</a>()" )
Detailed Description
Public Functions
ConsoleDocClass(PhysicsForce , "@brief Helper object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> gameplay physical <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">forces.\n\n</a>" "%PhysicsForces can be created and \"attached\" to other @link <a href="/coding/class/classphysicsbody/">PhysicsBody</a> PhysicsBodies@endlink " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> attract them <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the position of the PhysicsForce." "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Physics\n</a>" )
DefineEngineMethod(PhysicsForce , attach , void , (Point3F start, Point3F direction, F32 maxDist) , "@brief Attempts <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> associate the <a href="/coding/class/classphysicsforce/">PhysicsForce</a> with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">PhysicsBody.\n\n</a>" "Performs <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> physics ray cast of the provided length and direction. The %<a href="/coding/class/classphysicsforce/">PhysicsForce</a> " "will attach itself <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the first dynamic <a href="/coding/class/classphysicsbody/">PhysicsBody</a> the ray collides with. " "On every tick, the attached body will be attracted towards the position of the %<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">PhysicsForce.\n\n</a>" "A %<a href="/coding/class/classphysicsforce/">PhysicsForce</a> can only be attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> one body at <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">time.\n\n</a>" " @note To determine <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> an %attach was successful, check isAttached() immediately after " "calling this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">function.n\n</a>" )
DefineEngineMethod(PhysicsForce , detach , void , (Point3F force) , (Point3F::Zero) , "@brief Disassociates the <a href="/coding/class/classphysicsforce/">PhysicsForce</a> from any attached <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">PhysicsBody.\n\n</a>" "@param force Optional force <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> apply <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the attached <a href="/coding/class/classphysicsbody/">PhysicsBody</a> " "before <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">detaching.\n\n</a>" "@note Has no effect <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the %<a href="/coding/class/classphysicsforce/">PhysicsForce</a> is not attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">anything.\n\n</a>" )
DefineEngineMethod(PhysicsForce , isAttached , bool , () , "@brief Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the %<a href="/coding/class/classphysicsforce/">PhysicsForce</a> is currently attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> an <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@see <a href="/coding/class/classphysicsforce/#classphysicsforce_1a75a89178a0bcf6cb288b18a3a23170f5">PhysicsForce::attach</a>()" )
IMPLEMENT_CONOBJECT(PhysicsForce )
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#include "platform/platform.h" 25#include "T3D/physics/physicsForce.h" 26 27#include "T3D/physics/physicsPlugin.h" 28#include "T3D/physics/physicsWorld.h" 29#include "T3D/physics/physicsBody.h" 30#include "console/engineAPI.h" 31 32 33IMPLEMENT_CONOBJECT(PhysicsForce); 34 35 36ConsoleDocClass( PhysicsForce, 37 "@brief Helper object for gameplay physical forces.\n\n" 38 "%PhysicsForces can be created and \"attached\" to other @link PhysicsBody PhysicsBodies@endlink " 39 "to attract them to the position of the PhysicsForce." 40 "@ingroup Physics\n" 41); 42 43 44PhysicsForce::PhysicsForce() 45 : 46 mWorld( NULL ), 47 mForce(0.0f), 48 mPhysicsTick( false ), 49 mBody( NULL ) 50{ 51} 52 53PhysicsForce::~PhysicsForce() 54{ 55} 56 57void PhysicsForce::initPersistFields() 58{ 59 Parent::initPersistFields(); 60} 61 62 63bool PhysicsForce::onAdd() 64{ 65 if ( !Parent::onAdd() ) 66 return false; 67 68 // Find the physics world we're in. 69 if ( PHYSICSMGR ) 70 mWorld = PHYSICSMGR->getWorld( isServerObject() ? "server" : "client" ); 71 72 setProcessTick( true ); 73 getProcessList()->preTickSignal().notify( this, &PhysicsForce::_preTick ); 74 75 return true; 76} 77 78void PhysicsForce::onRemove() 79{ 80 mWorld = NULL; 81 mBody = NULL; 82 getProcessList()->preTickSignal().remove( this, &PhysicsForce::_preTick ); 83 setProcessTick( false ); 84 85 Parent::onRemove(); 86} 87 88void PhysicsForce::attach( const Point3F &start, const Point3F &direction, F32 maxDist ) 89{ 90 detach(); 91 92 // If there is no physics world then we cannot apply any forces. 93 if ( !mWorld ) 94 return; 95 96 PhysicsBody *body = mWorld->castRay( start, start + ( direction * maxDist ), PhysicsWorld::BT_Dynamic ); 97 if ( !body ) 98 return; 99 100 mBody = body; 101} 102 103void PhysicsForce::detach( const Point3F &force ) 104{ 105 if ( mBody && !force.isZero() ) 106 { 107 Point3F cMass = mBody->getCMassPosition(); 108 F32 mass = mBody->getMass(); 109 110 Point3F impulse = ( mass * force ) / TickSec; 111 mBody->applyImpulse( cMass, impulse ); 112 } 113 114 mBody = NULL; 115} 116 117void PhysicsForce::onMount( SceneObject *obj, S32 node ) 118{ 119 Parent::onMount( obj, node ); 120 121 processAfter( obj ); 122 123 MatrixF mat( true ); 124 mMount.object->getMountTransform( mMount.node, mMount.xfm, &mat ); 125 setTransform( mat ); 126} 127 128void PhysicsForce::onUnmount( SceneObject *obj, S32 node ) 129{ 130 clearProcessAfter(); 131 Parent::onUnmount( obj, node ); 132} 133 134void PhysicsForce::_preTick() 135{ 136 // How Torque works we sometimes get double or more 137 // ticks within a single simulation step. This occurs 138 // for various reasons including odd timesteps and low 139 // framerate. 140 // 141 // In order to keep performance from plumeting we do 142 // not tick physics multiple times... instead it just 143 // looses time. 144 // 145 // We set this variable below to let processTick know 146 // that physics hasn't stepped yet and to skip processing. 147 // 148 // This doesn't completely solve the issue, but it does 149 // make things much better. 150 // 151 mPhysicsTick = true; 152} 153 154void PhysicsForce::processTick( const Move * ) 155{ 156 if ( isMounted() ) 157 { 158 MatrixF test( true ); 159 test.setPosition( Point3F( 0, 4, 0 ) ); 160 AssertFatal( test != mMount.xfm, "Error!" ); 161 162 MatrixF mat( true ); 163 mMount.object->getMountTransform( mMount.node, mMount.xfm, &mat ); 164 setTransform( mat ); 165 } 166 167 // Nothing to do without a body or if physics hasn't ticked. 168 if ( !mBody || !mPhysicsTick ) 169 return; 170 171 mPhysicsTick = false; 172 173 // If we lost the body then release it. 174 if ( !mBody->isDynamic() || !mBody->isSimulationEnabled() ) 175 { 176 detach(); 177 return; 178 } 179 180 // Get our distance to the body. 181 Point3F cMass = mBody->getCMassPosition(); 182 Point3F vector = getPosition() - cMass; 183 184 // Apply the force! 185 F32 mass = mBody->getMass(); 186 Point3F impulse = ( mass * vector ) / TickSec; 187 188 // Counter balance the linear impulse. 189 Point3F linVel = mBody->getLinVelocity(); 190 Point3F currentForce = linVel * mass; 191 192 // Apply it. 193 mBody->applyImpulse( cMass, impulse - currentForce ); 194} 195 196DefineEngineMethod( PhysicsForce, attach, void, ( Point3F start, Point3F direction, F32 maxDist ),, 197 "@brief Attempts to associate the PhysicsForce with a PhysicsBody.\n\n" 198 "Performs a physics ray cast of the provided length and direction. The %PhysicsForce " 199 "will attach itself to the first dynamic PhysicsBody the ray collides with. " 200 "On every tick, the attached body will be attracted towards the position of the %PhysicsForce.\n\n" 201 "A %PhysicsForce can only be attached to one body at a time.\n\n" 202 "@note To determine if an %attach was successful, check isAttached() immediately after " 203 "calling this function.n\n") 204{ 205 object->attach( start, direction, maxDist ); 206} 207 208DefineEngineMethod( PhysicsForce, detach, void, ( Point3F force ), ( Point3F::Zero ), 209 "@brief Disassociates the PhysicsForce from any attached PhysicsBody.\n\n" 210 "@param force Optional force to apply to the attached PhysicsBody " 211 "before detaching.\n\n" 212 "@note Has no effect if the %PhysicsForce is not attached to anything.\n\n") 213{ 214 object->detach( force ); 215} 216 217DefineEngineMethod( PhysicsForce, isAttached, bool, (),, 218 "@brief Returns true if the %PhysicsForce is currently attached to an object.\n\n" 219 "@see PhysicsForce::attach()") 220{ 221 return object->isAttached(); 222} 223 224