Torque3D Documentation / _generateds / sceneSimpleZone.cpp

sceneSimpleZone.cpp

Engine/source/scene/zones/sceneSimpleZone.cpp

More...

Public Variables

bool

For frame signal.

Detailed Description

Public Variables

bool gEditingMission 

For frame signal.

  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 "scene/zones/sceneSimpleZone.h"
 26
 27#include "scene/sceneRenderState.h"
 28#include "scene/sceneManager.h"
 29#include "scene/zones/sceneTraversalState.h"
 30#include "scene/culling/sceneCullingVolume.h"
 31#include "core/stream/bitStream.h"
 32#include "console/engineAPI.h"
 33#include "platform/profiler.h"
 34
 35
 36extern bool gEditingMission;
 37
 38
 39//-----------------------------------------------------------------------------
 40
 41SceneSimpleZone::SceneSimpleZone()
 42   : mUseAmbientLightColor( false ),
 43     mAmbientLightColor( 0.1f, 0.1f, 0.1f, 1.f ),
 44     mIsRotated( false )
 45{
 46   // Box zones are unit cubes that are scaled to fit.
 47
 48   mObjScale.set( 10, 10, 10 );
 49   mObjBox.set(
 50      Point3F( -0.5f, -0.5f, -0.5f ),
 51      Point3F( 0.5f, 0.5f, 0.5f )
 52   );
 53}
 54
 55//-----------------------------------------------------------------------------
 56
 57void SceneSimpleZone::initPersistFields()
 58{
 59   addGroup( "Lighting" );
 60
 61      addProtectedField( "useAmbientLightColor", TypeBool, Offset( mUseAmbientLightColor, SceneSimpleZone ),
 62         &_setUseAmbientLightColor, &defaultProtectedGetFn,
 63         "Whether to use #ambientLightColor for ambient lighting in this zone or the global ambient color." );
 64      addProtectedField( "ambientLightColor", TypeColorF, Offset( mAmbientLightColor, SceneSimpleZone ),
 65         &_setAmbientLightColor, &defaultProtectedGetFn,
 66         "Color of ambient lighting in this zone.\n\n"
 67         "Only used if #useAmbientLightColor is true." );
 68
 69   endGroup( "Lighting" );
 70
 71   Parent::initPersistFields();
 72}
 73
 74//-----------------------------------------------------------------------------
 75
 76String SceneSimpleZone::describeSelf() const
 77{
 78   String str = Parent::describeSelf();
 79   str += String::ToString( "|zoneid: %i", getZoneRangeStart() );
 80   return str;
 81}
 82
 83//-----------------------------------------------------------------------------
 84
 85bool SceneSimpleZone::onSceneAdd()
 86{
 87   if( !Parent::onSceneAdd() )
 88      return false;
 89
 90   // Register our zone.
 91
 92   SceneZoneSpaceManager* manager = getSceneManager()->getZoneManager();
 93   if( manager )
 94      manager->registerZones( this, 1 );
 95
 96   return true;
 97}
 98
 99//-----------------------------------------------------------------------------
100
101U32 SceneSimpleZone::packUpdate( NetConnection* connection, U32 mask, BitStream* stream )
102{
103   U32 retMask = Parent::packUpdate( connection, mask, stream );
104
105   if( stream->writeFlag( mask & AmbientMask ) )
106   {
107      stream->writeFlag( mUseAmbientLightColor );
108      stream->writeFloat( mAmbientLightColor.red, 7 );
109      stream->writeFloat( mAmbientLightColor.green, 7 );
110      stream->writeFloat( mAmbientLightColor.blue, 7 );
111      stream->writeFloat( mAmbientLightColor.alpha, 7 );
112   }
113
114   return retMask;
115}
116
117//-----------------------------------------------------------------------------
118
119void SceneSimpleZone::unpackUpdate( NetConnection* connection, BitStream* stream )
120{
121   Parent::unpackUpdate( connection, stream );
122
123   if( stream->readFlag() ) // AmbientMask
124   {
125      mUseAmbientLightColor = stream->readFlag();
126      mAmbientLightColor.red = stream->readFloat( 7 );
127      mAmbientLightColor.green = stream->readFloat( 7 );
128      mAmbientLightColor.blue = stream->readFloat( 7 );
129      mAmbientLightColor.alpha = stream->readFloat( 7 );
130   }
131}
132
133//-----------------------------------------------------------------------------
134
135void SceneSimpleZone::setUseAmbientLightColor( bool value )
136{
137   if( mUseAmbientLightColor == value )
138      return;
139
140   mUseAmbientLightColor = value;
141   if( isServerObject() )
142      setMaskBits( AmbientMask );
143}
144
145//-----------------------------------------------------------------------------
146
147void SceneSimpleZone::setAmbientLightColor( const LinearColorF& color )
148{
149   mAmbientLightColor = color;
150   if( isServerObject() )
151      setMaskBits( AmbientMask );
152}
153
154//-----------------------------------------------------------------------------
155
156bool SceneSimpleZone::getZoneAmbientLightColor( U32 zone, LinearColorF& outColor ) const
157{
158   AssertFatal( zone == getZoneRangeStart(), "SceneSimpleZone::getZoneAmbientLightColor - Invalid zone ID!" );
159
160   if( !mUseAmbientLightColor )
161      return false;
162
163   outColor = mAmbientLightColor;
164   return true;
165}
166
167//-----------------------------------------------------------------------------
168
169U32 SceneSimpleZone::getPointZone( const Point3F& p )
170{
171   if( !containsPoint( p ) )
172      return SceneZoneSpaceManager::InvalidZoneId;
173
174   return getZoneRangeStart();
175}
176
177//-----------------------------------------------------------------------------
178
179bool SceneSimpleZone::getOverlappingZones( const Box3F& aabb, U32* outZones, U32& outNumZones )
180{
181   PROFILE_SCOPE( SceneBoxZone_getOverlappingZones );
182
183   bool isOverlapped = false;
184   bool isContained = false;
185
186   // If the zone has not been rotated, we can simply use straightforward
187   // AABB/AABB intersection based on the world boxes of the zone and the
188   // object.
189   //
190   // If, however, the zone has been rotated, then we must use the zone's
191   // OBB and test that against the object's AABB.
192
193   if( !mIsRotated )
194   {
195      isOverlapped = mWorldBox.isOverlapped( aabb );
196      isContained = isOverlapped && mWorldBox.isContained( aabb );
197   }
198   else
199   {
200      // Check if the zone's OBB intersects the object's AABB.
201
202      isOverlapped = aabb.collideOrientedBox(
203         getScale() / 2.f,
204         getTransform()
205      );
206
207      // If so, check whether the object's AABB is fully contained
208      // inside the zone's OBB.
209
210      if( isOverlapped )
211      {
212         isContained = true;
213
214         for( U32 i = 0; i < Box3F::NUM_POINTS; ++ i )
215         {
216            Point3F cornerPoint = aabb.computeVertex( i );
217            if( !mOrientedWorldBox.isContained( cornerPoint ) )
218            {
219               isContained = false;
220               break;
221            }
222         }
223      }
224   }
225
226   if( isOverlapped )
227   {
228      outNumZones = 1;
229      outZones[ 0 ] = getZoneRangeStart();
230   }
231   else
232      outNumZones = 0;
233
234   return !isContained;
235}
236
237//-----------------------------------------------------------------------------
238
239void SceneSimpleZone::setTransform( const MatrixF& mat )
240{
241   Parent::setTransform( mat );
242
243   // Find out whether the zone has been rotated.
244
245   EulerF rotation = getTransform().toEuler();
246   mIsRotated =   !mIsZero( rotation.x ) ||
247                  !mIsZero( rotation.y ) ||
248                  !mIsZero( rotation.z );
249
250   // Update the OBB.
251
252   _updateOrientedWorldBox();
253}
254
255//-----------------------------------------------------------------------------
256
257void SceneSimpleZone::prepRenderImage( SceneRenderState* state )
258{
259   if( isRootZone() )
260      return;
261
262   Parent::prepRenderImage( state );
263}
264
265//-----------------------------------------------------------------------------
266
267void SceneSimpleZone::traverseZones( SceneTraversalState* state )
268{
269   traverseZones( state, getZoneRangeStart() );
270}
271
272//-----------------------------------------------------------------------------
273
274void SceneSimpleZone::traverseZones( SceneTraversalState* state, U32 startZoneId )
275{
276   PROFILE_SCOPE( SceneSimpleZone_traverseZones );
277   AssertFatal( startZoneId == getZoneRangeStart(), "SceneSimpleZone::traverseZones - Invalid start zone ID!" );
278
279   // If we aren't the root of the traversal, do a number of checks
280   // to see if we can early out of the traversal here.  The primary reason
281   // we don't do the checks if we are the root is because of the frustum
282   // near plane.  The start zone of a traversal is selected based on the
283   // current viewpoint.  However, that point still has some space in between
284   // it and the near plane so if we end up with a case where that's all the
285   // space that is needed to cull away our starting zone, we won't see any
286   // traversal at all and get a blank scene back even if the starting zone
287   // would actually hand the traversal over to other zones and eventually
288   // discover visible space.
289
290   if( state->getTraversalDepth() > 0 )
291   {
292      // If we have already visited this zone in this traversal chain,
293      // exit out.  This can happen when zones are grouped together.
294      // Note that this can also happen with the outdoor zone since it isn't
295      // convex.  However, in that case, this acts as a nice side optimization
296      // we get since if the outdoor zone is already on the stack, our culling
297      // culling volume can only be smaller than the one we started with and thus
298      // by earlying out here, we prevent adding a pointless culling volume
299      // to the zone.
300
301      //TODO: would be nice to catch this via "visibility changed?" checks but
302      //    that's non-trivial
303
304      if( state->haveVisitedZone( getZoneRangeStart() ) )
305         return;
306
307      // First check whether we even intersect the given frustum at all.
308
309      if( mIsRotated )
310      {
311         // Space has been rotated, so do a frustum/OBB check.
312         if( !state->getCurrentCullingVolume().test( _getOrientedWorldBox() ) )
313            return;
314      }
315      else
316      {
317         // Space has not been rotated, so we can do a faster frustum/ABB check.
318         if( !state->getCurrentCullingVolume().test( getWorldBox() ) )
319            return;
320      }
321   }
322
323   // Add the current culling volume to the culling state for this zone.
324   // If that doesn't result in new space becoming visible, we can terminate the traversal
325   // here.
326
327   if( !state->getCullingState()->addCullingVolumeToZone( startZoneId, state->getCurrentCullingVolume() ) )
328      return;
329
330   // Add our occluders to the rendering state.
331
332   _addOccludersToCullingState( state->getCullingState() );
333
334   // Merge the zone into the traversal area.
335
336   state->addToTraversedArea( getWorldBox() );
337
338   // Push our zone ID on the traversal stack and traverse into our
339   // connected zone managers.
340
341   state->pushZone( startZoneId );
342   _traverseConnectedZoneSpaces( state );
343   state->popZone();
344}
345
346//-----------------------------------------------------------------------------
347
348bool SceneSimpleZone::_setUseAmbientLightColor( void* object, const char* index, const char* data )
349{
350   SceneSimpleZone* zone = reinterpret_cast< SceneSimpleZone* >( object );
351   zone->setUseAmbientLightColor( EngineUnmarshallData< bool>()( data ) );
352   return false;
353}
354
355//-----------------------------------------------------------------------------
356
357bool SceneSimpleZone::_setAmbientLightColor( void* object, const char* index, const char* data )
358{
359   SceneSimpleZone* zone = reinterpret_cast< SceneSimpleZone* >( object );
360   zone->setAmbientLightColor( EngineUnmarshallData< LinearColorF>()( data ) );
361   return false;
362}
363