accumulationVolume.cpp
Engine/source/T3D/accumulationVolume.cpp
Public Variables
Public Functions
ConsoleDocClass(AccumulationVolume , "@brief An invisible shape that allow objects within it <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> have an accumulation <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">map.\n\n</a>" "<a href="/coding/class/classaccumulationvolume/">AccumulationVolume</a> is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add additional realism <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> scene. It's <a href="/coding/file/x86unixmain_8cpp/#x86unixmain_8cpp_1a217dbf8b442f20279ea00b898af96f52">main</a> use is in outdoor scenes " " where objects could benefit from overlaying environment accumulation textures such as sand, snow , <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">etc.\n\n</a>" "Objects within the volume must have accumulation enabled in their material. \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" " @ingroup enviroMisc" )
Detailed Description
Public Variables
GFXTexHandle gLevelAccuMap
Public Functions
ConsoleDocClass(AccumulationVolume , "@brief An invisible shape that allow objects within it <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> have an accumulation <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">map.\n\n</a>" "<a href="/coding/class/classaccumulationvolume/">AccumulationVolume</a> is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add additional realism <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> scene. It's <a href="/coding/file/x86unixmain_8cpp/#x86unixmain_8cpp_1a217dbf8b442f20279ea00b898af96f52">main</a> use is in outdoor scenes " " where objects could benefit from overlaying environment accumulation textures such as sand, snow , <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">etc.\n\n</a>" "Objects within the volume must have accumulation enabled in their material. \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" " @ingroup enviroMisc" )
IMPLEMENT_CO_NETOBJECT_V1(AccumulationVolume )
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/accumulationVolume.h" 26 27#include "scene/sceneManager.h" 28#include "scene/sceneRenderState.h" 29#include "gfx/gfxDevice.h" 30#include "gfx/gfxDrawUtil.h" 31#include "gfx/sim/debugDraw.h" 32#include "util/tempAlloc.h" 33#include "materials/materialDefinition.h" 34#include "materials/materialManager.h" 35#include "materials/materialFeatureTypes.h" 36#include "materials/matInstance.h" 37#include "console/consoleTypes.h" 38#include "core/stream/bitStream.h" 39#include "gfx/gfxDevice.h" 40#include "console/console.h" 41#include "console/engineAPI.h" 42#include "gfx/gfxTextureHandle.h" 43#include "scene/sceneContainer.h" 44 45#include "math/mPolyhedron.impl.h" 46 47Vector< SimObjectPtr<SceneObject> > AccumulationVolume::smAccuObjects; 48Vector< SimObjectPtr<AccumulationVolume> > AccumulationVolume::smAccuVolumes; 49 50GFXTexHandle gLevelAccuMap; 51 52//#define DEBUG_DRAW 53 54IMPLEMENT_CO_NETOBJECT_V1( AccumulationVolume ); 55 56ConsoleDocClass( AccumulationVolume, 57 "@brief An invisible shape that allow objects within it to have an accumulation map.\n\n" 58 59 "AccumulationVolume is used to add additional realism to a scene. It's main use is in outdoor scenes " 60 " where objects could benefit from overlaying environment accumulation textures such as sand, snow, etc.\n\n" 61 62 "Objects within the volume must have accumulation enabled in their material. \n\n" 63 64 "@ingroup enviroMisc" 65); 66 67//----------------------------------------------------------------------------- 68 69AccumulationVolume::AccumulationVolume() 70 : mTransformDirty( true ), 71 mSilhouetteExtractor( mPolyhedron ) 72{ 73 VECTOR_SET_ASSOCIATION( mWSPoints ); 74 VECTOR_SET_ASSOCIATION( mVolumeQueryList ); 75 76 //mObjectFlags.set( VisualOccluderFlag ); 77 78 mNetFlags.set( Ghostable | ScopeAlways ); 79 mObjScale.set( 1.f, 1.f, 1.f ); 80 mObjBox.set( 81 Point3F( -0.5f, -0.5f, -0.5f ), 82 Point3F( 0.5f, 0.5f, 0.5f ) 83 ); 84 85 mObjToWorld.identity(); 86 mWorldToObj.identity(); 87 88 // Accumulation Texture. 89 mTextureName = ""; 90 mAccuTexture = NULL; 91 92 resetWorldBox(); 93} 94 95AccumulationVolume::~AccumulationVolume() 96{ 97 mAccuTexture = NULL; 98} 99 100void AccumulationVolume::initPersistFields() 101{ 102 addProtectedField( "texture", TypeStringFilename, Offset( mTextureName, AccumulationVolume ), 103 &_setTexture, &defaultProtectedGetFn, "Accumulation texture." ); 104 105 Parent::initPersistFields(); 106} 107 108//----------------------------------------------------------------------------- 109 110void AccumulationVolume::consoleInit() 111{ 112 // Disable rendering of occlusion volumes by default. 113 getStaticClassRep()->mIsRenderEnabled = false; 114} 115 116//----------------------------------------------------------------------------- 117 118bool AccumulationVolume::onAdd() 119{ 120 if( !Parent::onAdd() ) 121 return false; 122 123 // Prepare some client side things. 124 if ( isClientObject() ) 125 { 126 smAccuVolumes.push_back(this); 127 refreshVolumes(); 128 } 129 130 // Set up the silhouette extractor. 131 mSilhouetteExtractor = SilhouetteExtractorType( mPolyhedron ); 132 133 return true; 134} 135 136void AccumulationVolume::onRemove() 137{ 138 if ( isClientObject() ) 139 { 140 smAccuVolumes.remove(this); 141 refreshVolumes(); 142 } 143 Parent::onRemove(); 144} 145 146//----------------------------------------------------------------------------- 147 148void AccumulationVolume::_renderObject( ObjectRenderInst* ri, SceneRenderState* state, BaseMatInstance* overrideMat ) 149{ 150 Parent::_renderObject( ri, state, overrideMat ); 151 152 #ifdef DEBUG_DRAW 153 if( state->isDiffusePass() ) 154 DebugDrawer::get()->drawPolyhedronDebugInfo( mPolyhedron, getTransform(), getScale() ); 155 #endif 156} 157 158//----------------------------------------------------------------------------- 159 160void AccumulationVolume::setTransform( const MatrixF& mat ) 161{ 162 Parent::setTransform( mat ); 163 mTransformDirty = true; 164 refreshVolumes(); 165} 166 167//----------------------------------------------------------------------------- 168 169void AccumulationVolume::buildSilhouette( const SceneCameraState& cameraState, Vector< Point3F>& outPoints ) 170{ 171 // Extract the silhouette of the polyhedron. This works differently 172 // depending on whether we project orthogonally or in perspective. 173 174 TempAlloc< U32> indices( mPolyhedron.getNumPoints() ); 175 U32 numPoints; 176 177 if( cameraState.getFrustum().isOrtho() ) 178 { 179 // Transform the view direction into object space. 180 181 Point3F osViewDir; 182 getWorldTransform().mulV( cameraState.getViewDirection(), &osViewDir ); 183 184 // And extract the silhouette. 185 186 SilhouetteExtractorOrtho< PolyhedronType> extractor( mPolyhedron ); 187 numPoints = extractor.extractSilhouette( osViewDir, indices, indices.size ); 188 } 189 else 190 { 191 // Create a transform to go from view space to object space. 192 193 MatrixF camView( true ); 194 camView.scale( Point3F( 1.0f / getScale().x, 1.0f / getScale().y, 1.0f / getScale().z ) ); 195 camView.mul( getRenderWorldTransform() ); 196 camView.mul( cameraState.getViewWorldMatrix() ); 197 198 // Do a perspective-correct silhouette extraction. 199 200 numPoints = mSilhouetteExtractor.extractSilhouette( 201 camView, 202 indices, indices.size ); 203 } 204 205 // If we haven't yet, transform the polyhedron's points 206 // to world space. 207 208 if( mTransformDirty ) 209 { 210 const U32 numPolyPoints = mPolyhedron.getNumPoints(); 211 const PolyhedronType::PointType* points = getPolyhedron().getPoints(); 212 213 mWSPoints.setSize(numPolyPoints); 214 for( U32 i = 0; i < numPolyPoints; ++ i ) 215 { 216 Point3F p = points[ i ]; 217 p.convolve( getScale() ); 218 getTransform().mulP( p, &mWSPoints[ i ] ); 219 } 220 221 mTransformDirty = false; 222 } 223 224 // Now store the points. 225 226 outPoints.setSize( numPoints ); 227 for( U32 i = 0; i < numPoints; ++ i ) 228 outPoints[ i ] = mWSPoints[ indices[ i ] ]; 229} 230 231//----------------------------------------------------------------------------- 232 233U32 AccumulationVolume::packUpdate( NetConnection *connection, U32 mask, BitStream *stream ) 234{ 235 U32 retMask = Parent::packUpdate( connection, mask, stream ); 236 237 if (stream->writeFlag(mask & InitialUpdateMask)) 238 { 239 stream->write( mTextureName ); 240 } 241 242 return retMask; 243} 244 245void AccumulationVolume::unpackUpdate( NetConnection *connection, BitStream *stream ) 246{ 247 Parent::unpackUpdate( connection, stream ); 248 249 if (stream->readFlag()) 250 { 251 stream->read( &mTextureName ); 252 setTexture(mTextureName); 253 } 254} 255 256//----------------------------------------------------------------------------- 257 258void AccumulationVolume::inspectPostApply() 259{ 260 Parent::inspectPostApply(); 261 setMaskBits(U32(-1) ); 262} 263 264void AccumulationVolume::setTexture( const String& name ) 265{ 266 mTextureName = name; 267 if ( isClientObject() && mTextureName.isNotEmpty() ) 268 { 269 mAccuTexture.set(mTextureName, &GFXStaticTextureSRGBProfile, "AccumulationVolume::mAccuTexture"); 270 if ( mAccuTexture.isNull() ) 271 Con::warnf( "AccumulationVolume::setTexture - Unable to load texture: %s", mTextureName.c_str() ); 272 } 273 refreshVolumes(); 274} 275 276//----------------------------------------------------------------------------- 277// Static Functions 278//----------------------------------------------------------------------------- 279bool AccumulationVolume::_setTexture( void *object, const char *index, const char *data ) 280{ 281 AccumulationVolume* volume = reinterpret_cast< AccumulationVolume* >( object ); 282 volume->setTexture( data ); 283 return false; 284} 285 286void AccumulationVolume::refreshVolumes() 287{ 288 // This function tests each accumulation object to 289 // see if it's within the bounds of an accumulation 290 // volume. If so, it will pass on the accumulation 291 // texture of the volume to the object. 292 293 // This function should only be called when something 294 // global like change of volume or material occurs. 295 296 // Clear old data. 297 for (S32 n = 0; n < smAccuObjects.size(); ++n) 298 { 299 SimObjectPtr<SceneObject> object = smAccuObjects[n]; 300 if ( object.isValid() ) 301 object->mAccuTex = gLevelAccuMap; 302 } 303 304 // 305 for (S32 i = 0; i < smAccuVolumes.size(); ++i) 306 { 307 SimObjectPtr<AccumulationVolume> volume = smAccuVolumes[i]; 308 if ( volume.isNull() ) continue; 309 310 for (S32 n = 0; n < smAccuObjects.size(); ++n) 311 { 312 SimObjectPtr<SceneObject> object = smAccuObjects[n]; 313 if ( object.isNull() ) continue; 314 315 if ( volume->containsPoint(object->getPosition()) ) 316 object->mAccuTex = volume->mAccuTexture; 317 } 318 } 319} 320 321// Accumulation Object Management. 322void AccumulationVolume::addObject(SimObjectPtr<SceneObject> object) 323{ 324 smAccuObjects.push_back(object); 325 refreshVolumes(); 326} 327 328void AccumulationVolume::removeObject(SimObjectPtr<SceneObject> object) 329{ 330 smAccuObjects.remove(object); 331 refreshVolumes(); 332} 333 334void AccumulationVolume::updateObject(SceneObject* object) 335{ 336 // This function is called when an individual object 337 // has been moved. Tests to see if it's in any of the 338 // accumulation volumes. 339 340 // We use ZERO instead of NULL so the accumulation 341 // texture will be updated in renderMeshMgr. 342 object->mAccuTex = gLevelAccuMap; 343 344 for (S32 i = 0; i < smAccuVolumes.size(); ++i) 345 { 346 SimObjectPtr<AccumulationVolume> volume = smAccuVolumes[i]; 347 if ( volume.isNull() ) continue; 348 349 if ( volume->containsPoint(object->getPosition()) ) 350 object->mAccuTex = volume->mAccuTexture; 351 } 352} 353