mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 04:34:48 +00:00
190 lines
6.2 KiB
C++
190 lines
6.2 KiB
C++
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "platform/platform.h"
|
|
#include "T3D/occlusionVolume.h"
|
|
|
|
#include "scene/sceneManager.h"
|
|
#include "scene/sceneRenderState.h"
|
|
#include "gfx/gfxDevice.h"
|
|
#include "gfx/gfxDrawUtil.h"
|
|
#include "gfx/sim/debugDraw.h"
|
|
#include "util/tempAlloc.h"
|
|
|
|
#include "math/mPolyhedron.impl.h"
|
|
|
|
|
|
//#define DEBUG_DRAW
|
|
|
|
|
|
IMPLEMENT_CO_NETOBJECT_V1( OcclusionVolume );
|
|
|
|
ConsoleDocClass( OcclusionVolume,
|
|
"@brief An invisible shape that causes objects hidden from view behind it to not be rendered.\n\n"
|
|
|
|
"OcclusionVolume is a class for scene optimization. It's main use is for outdoor spaces where zones "
|
|
"and portals do not help in optimizing scene culling as they almost only make sense for modeling visibility "
|
|
"in indoor scenarios (and for connecting indoor spaces to outdoor spaces).\n\n"
|
|
|
|
"During rendering, every object that is fully behind an occluder \n\n"
|
|
|
|
"Be aware that occluders add overhead to scene culling. Only if this overhead is outweighed by the time "
|
|
"saved by not rendering hidden objects, is the occluder actually effective. Because of this, chose only those "
|
|
"spots for placing occluders where a significant number of objects will be culled from points that the player "
|
|
"will actually be at during the game.\n\n"
|
|
|
|
"Like zones and portals, OcclusionVolumes may have a default box shape or a more complex \n\n"
|
|
|
|
"@see Scene::maxOccludersPerZone\n"
|
|
"@see Scene::occluderMinWidthPercentage\n"
|
|
"@see Scene::occluderMinHeightPercentage\n"
|
|
"@ingroup enviroMisc"
|
|
);
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
OcclusionVolume::OcclusionVolume()
|
|
: mTransformDirty( true ),
|
|
mSilhouetteExtractor( mPolyhedron )
|
|
{
|
|
VECTOR_SET_ASSOCIATION( mWSPoints );
|
|
|
|
mObjectFlags.set( VisualOccluderFlag );
|
|
|
|
mObjScale.set( 1.f, 1.f, 1.f );
|
|
mObjBox.set(
|
|
Point3F( -0.5f, -0.5f, -0.5f ),
|
|
Point3F( 0.5f, 0.5f, 0.5f )
|
|
);
|
|
|
|
mObjToWorld.identity();
|
|
mWorldToObj.identity();
|
|
|
|
resetWorldBox();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void OcclusionVolume::consoleInit()
|
|
{
|
|
// Disable rendering of occlusion volumes by default.
|
|
getStaticClassRep()->mIsRenderEnabled = false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool OcclusionVolume::onAdd()
|
|
{
|
|
if( !Parent::onAdd() )
|
|
return false;
|
|
|
|
// Set up the silhouette extractor.
|
|
mSilhouetteExtractor = SilhouetteExtractorType( mPolyhedron );
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void OcclusionVolume::_renderObject( ObjectRenderInst* ri, SceneRenderState* state, BaseMatInstance* overrideMat )
|
|
{
|
|
Parent::_renderObject( ri, state, overrideMat );
|
|
|
|
#ifdef DEBUG_DRAW
|
|
if( state->isDiffusePass() )
|
|
DebugDrawer::get()->drawPolyhedronDebugInfo( mPolyhedron, getTransform(), getScale() );
|
|
#endif
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void OcclusionVolume::setTransform( const MatrixF& mat )
|
|
{
|
|
Parent::setTransform( mat );
|
|
mTransformDirty = true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void OcclusionVolume::buildSilhouette( const SceneCameraState& cameraState, Vector< Point3F >& outPoints )
|
|
{
|
|
// Extract the silhouette of the polyhedron. This works differently
|
|
// depending on whether we project orthogonally or in perspective.
|
|
|
|
TempAlloc< U32 > indices( mPolyhedron.getNumPoints() );
|
|
U32 numPoints;
|
|
|
|
if( cameraState.getFrustum().isOrtho() )
|
|
{
|
|
// Transform the view direction into object space.
|
|
|
|
Point3F osViewDir;
|
|
getWorldTransform().mulV( cameraState.getViewDirection(), &osViewDir );
|
|
|
|
// And extract the silhouette.
|
|
|
|
SilhouetteExtractorOrtho< PolyhedronType > extractor( mPolyhedron );
|
|
numPoints = extractor.extractSilhouette( osViewDir, indices, indices.size );
|
|
}
|
|
else
|
|
{
|
|
// Create a transform to go from view space to object space.
|
|
|
|
MatrixF camView( true );
|
|
camView.scale( Point3F( 1.0f / getScale().x, 1.0f / getScale().y, 1.0f / getScale().z ) );
|
|
camView.mul( getRenderWorldTransform() );
|
|
camView.mul( cameraState.getViewWorldMatrix() );
|
|
|
|
// Do a perspective-correct silhouette extraction.
|
|
|
|
numPoints = mSilhouetteExtractor.extractSilhouette(
|
|
camView,
|
|
indices, indices.size );
|
|
}
|
|
|
|
// If we haven't yet, transform the polyhedron's points
|
|
// to world space.
|
|
|
|
if( mTransformDirty )
|
|
{
|
|
const U32 numPoints = mPolyhedron.getNumPoints();
|
|
const PolyhedronType::PointType* points = getPolyhedron().getPoints();
|
|
|
|
mWSPoints.setSize( numPoints );
|
|
for( U32 i = 0; i < numPoints; ++ i )
|
|
{
|
|
Point3F p = points[ i ];
|
|
p.convolve( getScale() );
|
|
getTransform().mulP( p, &mWSPoints[ i ] );
|
|
}
|
|
|
|
mTransformDirty = false;
|
|
}
|
|
|
|
// Now store the points.
|
|
|
|
outPoints.setSize( numPoints );
|
|
for( U32 i = 0; i < numPoints; ++ i )
|
|
outPoints[ i ] = mWSPoints[ indices[ i ] ];
|
|
}
|