Fix Ambient Occlusion Calculator to accept functors, functions and lambdas

By changing the 'pass by value' to be a 'pass by const reference' (and
adding some const qualifiers) the calculator can take any of the three
types.

Performance could be improved further using C++11 perfect forwarding to
pass the function on without changing a thing. I added a comment to remind
us of this.

Also added a test for passing a function and a (commented out) test for
passing a lambda.
This commit is contained in:
Matt Williams 2012-10-28 15:41:53 +00:00
parent d6640f64d0
commit bb87e9e628
3 changed files with 22 additions and 6 deletions

View File

@ -49,9 +49,8 @@ namespace PolyVox
class AmbientOcclusionCalculatorRaycastCallback
{
public:
AmbientOcclusionCalculatorRaycastCallback(IsVoxelTransparentCallback isVoxelTransparentCallback)
AmbientOcclusionCalculatorRaycastCallback(IsVoxelTransparentCallback isVoxelTransparentCallback) : mIsVoxelTransparentCallback(isVoxelTransparentCallback)
{
mIsVoxelTransparentCallback = isVoxelTransparentCallback;
}
bool operator()(const SimpleVolume<uint8_t>::Sampler& sampler)
@ -65,13 +64,19 @@ namespace PolyVox
return direct;
}
IsVoxelTransparentCallback mIsVoxelTransparentCallback;
const IsVoxelTransparentCallback& mIsVoxelTransparentCallback;
};
// NOTE: The callback needs to be a functor not a function. I haven't been
// able to work the required template magic to get functions working as well.
//
// Matt: If you make the function take a "IsVoxelTransparentCallback&&" then
// it will forward it on. Works for functors, functions and lambdas.
// This will be 'perfect forwarding' using 'universal references'
// This will require C++11 rvalue references which is why I haven't made the
// change yet.
template<typename VolumeType, typename IsVoxelTransparentCallback>
void calculateAmbientOcclusion(VolumeType* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement, IsVoxelTransparentCallback isVoxelTransparentCallback);
void calculateAmbientOcclusion(VolumeType* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement, const IsVoxelTransparentCallback& isVoxelTransparentCallback);
}
#include "PolyVoxCore/AmbientOcclusionCalculator.inl"

View File

@ -24,7 +24,7 @@ freely, subject to the following restrictions:
namespace PolyVox
{
template<typename VolumeType, typename IsVoxelTransparentCallback>
void calculateAmbientOcclusion(VolumeType* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement, IsVoxelTransparentCallback isVoxelTransparentCallback)
void calculateAmbientOcclusion(VolumeType* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement, const IsVoxelTransparentCallback& isVoxelTransparentCallback)
{
typename VolumeType::Sampler m_sampVolume(volInput);

View File

@ -33,12 +33,17 @@ using namespace PolyVox;
class IsVoxelTransparent
{
public:
bool operator()(uint8_t voxel)
bool operator()(uint8_t voxel) const
{
return voxel == 0;
}
};
bool isVoxelTransparentFunction(uint8_t voxel)
{
return voxel == 0;
}
void TestAmbientOcclusionGenerator::testExecute()
{
const int32_t g_uVolumeSideLength = 64;
@ -78,6 +83,12 @@ void TestAmbientOcclusionGenerator::testExecute()
QCOMPARE(static_cast<int>(ambientOcclusionResult[16][16][16]), 103);
QCOMPARE(static_cast<int>(ambientOcclusionResult[16][24][16]), 123);
QCOMPARE(static_cast<int>(ambientOcclusionResult[16][31][16]), 173);
//Just run a quick test to make sure that it compiles when taking a function pointer
calculateAmbientOcclusion(&volData, &ambientOcclusionResult, volData.getEnclosingRegion(), 32.0f, 8, &isVoxelTransparentFunction);
//Also test it using a lambda
//calculateAmbientOcclusion(&volData, &ambientOcclusionResult, volData.getEnclosingRegion(), 32.0f, 8, [](uint8_t voxel){return voxel == 0;});
}
QTEST_MAIN(TestAmbientOcclusionGenerator)