windEmitter.cpp
Engine/source/T3D/fx/windEmitter.cpp
Detailed Description
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/fx/windEmitter.h" 26 27#include "math/mBox.h" 28#include "core/tAlgorithm.h" 29#include "platform/profiler.h" 30 31 32Vector<WindEmitter*> WindEmitter::smAllEmitters; 33 34 35WindEmitter::WindEmitter() 36{ 37 smAllEmitters.push_back( this ); 38 39 mEnabled = true; 40 mScore = 0.0f; 41 mSphere.center.zero(); 42 mSphere.radius = 0.0f; 43 mStrength = 0.0f; 44 mTurbulenceFrequency = 0.0f; 45 mTurbulenceStrength = 0.0f; 46 mVelocity.zero(); 47} 48 49WindEmitter::~WindEmitter() 50{ 51 WindEmitterList::iterator iter = T3D::find( smAllEmitters.begin(), smAllEmitters.end(), this ); 52 smAllEmitters.erase( iter ); 53} 54 55void WindEmitter::setPosition( const Point3F& pos ) 56{ 57 mSphere.center = pos; 58} 59 60void WindEmitter::update( const Point3F& pos, const VectorF& velocity ) 61{ 62 mSphere.center = pos; 63 mVelocity = velocity; 64} 65 66void WindEmitter::setRadius( F32 radius ) 67{ 68 mSphere.radius = radius; 69} 70 71void WindEmitter::setStrength( F32 strength ) 72{ 73 mStrength = strength; 74} 75 76void WindEmitter::setTurbulency( F32 frequency, F32 strength ) 77{ 78 mTurbulenceFrequency = frequency; 79 mTurbulenceStrength = strength; 80} 81 82S32 QSORT_CALLBACK WindEmitter::_sortByScore(const void* a, const void* b) 83{ 84 return mSign((*(WindEmitter**)b)->mScore - (*(WindEmitter**)a)->mScore); 85} 86 87bool WindEmitter::findBest( const Point3F& cameraPos, 88 const VectorF& cameraDir, 89 F32 viewDistance, 90 U32 maxResults, 91 WindEmitterList* results ) 92{ 93 PROFILE_START(WindEmitter_findBest); 94 95 // Build a sphere from the camera point. 96 SphereF cameraSphere; 97 cameraSphere.center = cameraPos; 98 cameraSphere.radius = viewDistance; 99 100 // Collect the active spheres within the camera space and score them. 101 WindEmitterList best; 102 WindEmitterList::iterator iter = smAllEmitters.begin(); 103 for ( ; iter != smAllEmitters.end(); iter++ ) 104 { 105 const SphereF& sphere = *(*iter); 106 107 // Skip any spheres outside of our camera range or that are disabled. 108 if ( !(*iter)->mEnabled || !cameraSphere.isIntersecting( sphere ) ) 109 continue; 110 111 // Simple score calculation... 112 // 113 // score = ( radius / distance to camera ) * dot( cameraDir, vector from camera to sphere ) 114 // 115 Point3F vect = sphere.center - cameraSphere.center; 116 F32 dist = vect.len(); 117 (*iter)->mScore = dist * sphere.radius; 118 vect /= getMax( dist, 0.001f ); 119 (*iter)->mScore *= mDot( vect, cameraDir ); 120 121 best.push_back( *iter ); 122 } 123 124 // Sort the results by score! 125 dQsort( best.address(), best.size(), sizeof(WindEmitter*), &WindEmitter::_sortByScore ); 126 127 // Clip the results to the max requested. 128 if ( best.size() > maxResults ) 129 best.setSize( maxResults ); 130 131 // Merge the results and return. 132 results->merge( best ); 133 134 PROFILE_END(); // WindEmitter_findBest 135 136 return best.size() > 0; 137} 138