From 74752954240c0274f82a97d2427a9f6e16ed03bb Mon Sep 17 00:00:00 2001 From: "Herholz, Sebastian" Date: Thu, 15 Aug 2024 18:16:27 +0200 Subject: [PATCH] [format] Applying clang-format --- cmake/check_arm_neon.cpp | 2 +- openpgl/api/api.cpp | 377 +- openpgl/api/deviceCPU16.cpp | 10 +- openpgl/api/deviceCPU4.cpp | 10 +- openpgl/api/deviceCPU8.cpp | 10 +- openpgl/data/PathSegmentData.h | 230 +- openpgl/data/PathSegmentDataStorage.h | 295 +- openpgl/data/Range.h | 111 +- openpgl/data/SampleContainerInternal.h | 305 +- openpgl/data/SampleData.h | 322 +- openpgl/data/SampleDataStorage.h | 207 +- openpgl/data/SampleStatistics.h | 593 +- openpgl/device/Device.h | 182 +- .../DirectionalDistributionStatistics.h | 34 +- .../ISurfaceSamplingDistribution.h | 40 +- .../directional/IVolumeSamplingDistribution.h | 42 +- .../directional/OutgoingRadianceHistogram.h | 74 +- openpgl/directional/dqt/DQT.h | 308 +- openpgl/directional/dqt/DQTFactory.h | 217 +- .../dqt/DQTSurfaceSamplingDistribution.h | 52 +- .../dqt/DQTVolumeSamplingDistribution.h | 56 +- openpgl/directional/dqt/Rect.h | 28 +- openpgl/directional/dqt/SphereToSquare.h | 115 +- openpgl/directional/dqt/Traversal.h | 73 +- .../vmm/AdaptiveSplitandMergeFactory.h | 229 +- .../vmm/ParallaxAwareVonMisesFisherMixture.h | 804 +-- ...llaxAwareVonMisesFisherWeightedEMFactory.h | 907 ++- .../vmm/VMMChiSquareComponentMerger.h | 215 +- .../vmm/VMMChiSquareComponentSplitter.h | 647 +-- openpgl/directional/vmm/VMMPhaseFunctions.cpp | 4908 ++++++++--------- openpgl/directional/vmm/VMMPhaseFunctions.h | 78 +- .../vmm/VMMSurfaceSamplingDistribution.h | 65 +- .../vmm/VMMVolumeSamplingDistribution.h | 83 +- openpgl/field/Field.h | 516 +- openpgl/field/FieldStatistics.h | 48 +- openpgl/field/ISurfaceVolumeField.h | 24 +- openpgl/field/SurfaceVolumeField.h | 165 +- openpgl/imagespace/Denoiser.h | 63 +- openpgl/imagespace/ImageSpaceGuidingBuffer.h | 357 +- openpgl/include/openpgl/common.h | 250 +- openpgl/include/openpgl/compression.h | 158 +- openpgl/include/openpgl/config.h | 178 +- openpgl/include/openpgl/cpp/Common.h | 495 +- openpgl/include/openpgl/cpp/Device.h | 24 +- openpgl/include/openpgl/cpp/Distribution.h | 13 +- openpgl/include/openpgl/cpp/Field.h | 80 +- openpgl/include/openpgl/cpp/FieldConfig.h | 51 +- openpgl/include/openpgl/cpp/FieldStatistics.h | 41 +- .../openpgl/cpp/ImageSpaceGuidingBuffer.h | 49 +- openpgl/include/openpgl/cpp/OpenPGL.h | 8 +- openpgl/include/openpgl/cpp/PathSegment.h | 56 +- .../include/openpgl/cpp/PathSegmentStorage.h | 103 +- openpgl/include/openpgl/cpp/Region.h | 36 +- openpgl/include/openpgl/cpp/RussianRoulette.h | 132 +- openpgl/include/openpgl/cpp/SampleData.h | 20 +- openpgl/include/openpgl/cpp/SampleStorage.h | 90 +- .../openpgl/cpp/SurfaceSamplingDistribution.h | 160 +- .../openpgl/cpp/VolumeSamplingDistribution.h | 156 +- openpgl/include/openpgl/data.h | 81 +- openpgl/include/openpgl/device.h | 15 +- openpgl/include/openpgl/distribution.h | 15 +- openpgl/include/openpgl/field.h | 48 +- openpgl/include/openpgl/fieldstatistics.h | 16 +- .../include/openpgl/imagespaceguidingbuffer.h | 27 +- openpgl/include/openpgl/openpgl.h | 14 +- openpgl/include/openpgl/pathsegmentstorage.h | 51 +- openpgl/include/openpgl/region.h | 8 +- openpgl/include/openpgl/samplestorage.h | 51 +- .../openpgl/surfacesamplingdistribution.h | 38 +- .../openpgl/volumesamplingdistribution.h | 41 +- openpgl/openpgl_common.h | 393 +- openpgl/spatial/IRegion.h | 18 +- openpgl/spatial/KNN.h | 301 +- openpgl/spatial/Region.h | 224 +- openpgl/spatial/kdtree/KDTree.h | 412 +- openpgl/spatial/kdtree/KDTreeBuilder.h | 308 +- openpgl/spatial/kdtree/KDTreeStatistics.h | 34 +- tools/openpgl_bench/openpgl_bench.cpp | 367 +- tools/openpgl_bench/timer.h | 18 +- tools/openpgl_check/openpgl_check.cpp | 10 +- tools/openpgl_debug/openpgl_debug.cpp | 445 +- 81 files changed, 9206 insertions(+), 8631 deletions(-) diff --git a/cmake/check_arm_neon.cpp b/cmake/check_arm_neon.cpp index cf9ecb6..66c8db0 100644 --- a/cmake/check_arm_neon.cpp +++ b/cmake/check_arm_neon.cpp @@ -9,5 +9,5 @@ int main() { - return vaddvq_s32(vdupq_n_s32(1)); + return vaddvq_s32(vdupq_n_s32(1)); } diff --git a/openpgl/api/api.cpp b/openpgl/api/api.cpp index a179ac4..cb3ece8 100644 --- a/openpgl/api/api.cpp +++ b/openpgl/api/api.cpp @@ -2,20 +2,18 @@ // SPDX-License-Identifier: Apache-2.0 #include "../include/openpgl/openpgl.h" -//#include "../openpglTypes.h" +// #include "../openpglTypes.h" -#include "openpgl_common.h" - -#include "device/Device.h" -#include "field/ISurfaceVolumeField.h" -#include "field/FieldStatistics.h" -#include "directional/ISurfaceSamplingDistribution.h" -#include "directional/IVolumeSamplingDistribution.h" - -#include "data/PathSegmentDataStorage.h" #include "data/PathSegmentData.h" +#include "data/PathSegmentDataStorage.h" #include "data/SampleData.h" #include "data/SampleDataStorage.h" +#include "device/Device.h" +#include "directional/ISurfaceSamplingDistribution.h" +#include "directional/IVolumeSamplingDistribution.h" +#include "field/FieldStatistics.h" +#include "field/ISurfaceVolumeField.h" +#include "openpgl_common.h" #if defined(OPENPGL_IMAGE_SPACE_GUIDING_BUFFER) #include "imagespace/ImageSpaceGuidingBuffer.h" @@ -25,58 +23,54 @@ using namespace openpgl; -#define THROW_IF_NULL(obj, name) \ - if (obj == nullptr) \ - throw std::runtime_error(std::string("null ") + name + \ - std::string(" provided to ") + __FUNCTION__) +#define THROW_IF_NULL(obj, name) \ + if (obj == nullptr) \ + throw std::runtime_error(std::string("null ") + name + std::string(" provided to ") + __FUNCTION__) // convenience macros for repeated use of the above #define THROW_IF_NULL_OBJECT(obj) THROW_IF_NULL(obj, "handle") #define THROW_IF_NULL_STRING(str) THROW_IF_NULL(str, "string") -#define OPENPGL_CATCH_BEGIN try { -#define OPENPGL_CATCH_END(a) \ - } \ - catch (const std::bad_alloc &) \ - { \ - std::cout << \ - "Open PGL was unable to allocate memory" << std::endl; \ - return a; \ - } \ - catch (const std::exception &e) \ - { \ - std::cout << e.what() << std::endl; \ - return a; \ - } \ - catch (...) \ - { \ - std::cout << \ - "an unrecognized exception was caught" << std::endl; \ - return a; \ - } - -#define OPENPGL_CATCH_END_VOID \ - } \ - catch (const std::bad_alloc &) \ - { \ - std::cout << \ - "Open PGL was unable to allocate memory" << std::endl; \ - return; \ - } \ - catch (const std::exception &e) \ - { \ - std::cout << e.what() << std::endl; \ - return; \ - } \ - catch (...) \ - { \ - std::cout << \ - "an unrecognized exception was caught" << std::endl; \ - return; \ - } +#define OPENPGL_CATCH_BEGIN \ + try \ + { +#define OPENPGL_CATCH_END(a) \ + } \ + catch (const std::bad_alloc &) \ + { \ + std::cout << "Open PGL was unable to allocate memory" << std::endl; \ + return a; \ + } \ + catch (const std::exception &e) \ + { \ + std::cout << e.what() << std::endl; \ + return a; \ + } \ + catch (...) \ + { \ + std::cout << "an unrecognized exception was caught" << std::endl; \ + return a; \ + } -typedef ISurfaceVolumeField IGuidingField; +#define OPENPGL_CATCH_END_VOID \ + } \ + catch (const std::bad_alloc &) \ + { \ + std::cout << "Open PGL was unable to allocate memory" << std::endl; \ + return; \ + } \ + catch (const std::exception &e) \ + { \ + std::cout << e.what() << std::endl; \ + return; \ + } \ + catch (...) \ + { \ + std::cout << "an unrecognized exception was caught" << std::endl; \ + return; \ + } +typedef ISurfaceVolumeField IGuidingField; /////////////////////////////////////////////////////////////////////////////// // Field ////////////////////////////////////////////////////////////////////// @@ -84,19 +78,19 @@ typedef ISurfaceVolumeField IGuidingField; #define OPENPGL_FIELD_STRING "OPENPGL_" OPENPGL_VERSION_STRING "_FIELD" -extern "C" OPENPGL_DLLEXPORT PGLDevice pglNewDevice(PGL_DEVICE_TYPE deviceType, size_t numThreads)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT PGLDevice pglNewDevice(PGL_DEVICE_TYPE deviceType, size_t numThreads) OPENPGL_CATCH_BEGIN { #ifdef OPENPGL_DEVICE_TYPE_CPU_4 if (deviceType == PGL_DEVICE_TYPE_CPU_4) - return (PGLDevice) newDeviceCPU4(numThreads); + return (PGLDevice)newDeviceCPU4(numThreads); #endif #ifdef OPENPGL_DEVICE_TYPE_CPU_8 if (deviceType == PGL_DEVICE_TYPE_CPU_8) - return (PGLDevice) newDeviceCPU8(numThreads); + return (PGLDevice)newDeviceCPU8(numThreads); #endif #ifdef OPENPGL_DEVICE_TYPE_CPU_16 if (deviceType == PGL_DEVICE_TYPE_CPU_16) - return (PGLDevice) newDeviceCPU16(numThreads); + return (PGLDevice)newDeviceCPU16(numThreads); #endif throw std::runtime_error("invalid vectorSize parameter!"); @@ -109,31 +103,31 @@ extern "C" OPENPGL_DLLEXPORT void pglReleaseDevice(PGLDevice device) delete gDevice; } -extern "C" OPENPGL_DLLEXPORT PGLField pglDeviceNewField(PGLDevice device, PGLFieldArguments args)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT PGLField pglDeviceNewField(PGLDevice device, PGLFieldArguments args) OPENPGL_CATCH_BEGIN { THROW_IF_NULL_OBJECT(device); auto *gDevice = (IDevice *)device; - return (PGLField) gDevice->newField(args); + return (PGLField)gDevice->newField(args); } OPENPGL_CATCH_END(nullptr) -extern "C" OPENPGL_DLLEXPORT PGLField pglDeviceNewFieldFromFile(PGLDevice device, const char* fieldFileName)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT PGLField pglDeviceNewFieldFromFile(PGLDevice device, const char *fieldFileName) OPENPGL_CATCH_BEGIN { THROW_IF_NULL_OBJECT(device); THROW_IF_NULL_STRING(fieldFileName); auto *gDevice = (IDevice *)device; - return (PGLField) gDevice->newFieldFromFile(fieldFileName); + return (PGLField)gDevice->newFieldFromFile(fieldFileName); } OPENPGL_CATCH_END(nullptr) -extern "C" OPENPGL_DLLEXPORT void pglReleaseField(PGLField field)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT void pglReleaseField(PGLField field) OPENPGL_CATCH_BEGIN { auto *gField = (IGuidingField *)field; delete gField; } OPENPGL_CATCH_END_VOID -extern "C" OPENPGL_DLLEXPORT bool pglFieldStoreToFile(PGLField field, const char* fieldFileName)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT bool pglFieldStoreToFile(PGLField field, const char *fieldFileName) OPENPGL_CATCH_BEGIN { THROW_IF_NULL_OBJECT(field); THROW_IF_NULL_STRING(fieldFileName); @@ -142,7 +136,7 @@ extern "C" OPENPGL_DLLEXPORT bool pglFieldStoreToFile(PGLField field, const char } OPENPGL_CATCH_END(false) -extern "C" OPENPGL_DLLEXPORT size_t pglFieldGetIteration(PGLField field)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT size_t pglFieldGetIteration(PGLField field) OPENPGL_CATCH_BEGIN { auto *gField = (IGuidingField *)field; return gField->getIteration(); @@ -153,8 +147,8 @@ extern "C" OPENPGL_DLLEXPORT void pglFieldSetSceneBounds(PGLField field, pgl_box { auto *gField = (IGuidingField *)field; openpgl::BBox sceneBounds; - sceneBounds.lower = openpgl::Vector3(bounds.lower.x,bounds.lower.y,bounds.lower.z); - sceneBounds.upper = openpgl::Vector3(bounds.upper.x,bounds.upper.y,bounds.upper.z); + sceneBounds.lower = openpgl::Vector3(bounds.lower.x, bounds.lower.y, bounds.lower.z); + sceneBounds.upper = openpgl::Vector3(bounds.upper.x, bounds.upper.y, bounds.upper.z); gField->setSceneBounds(sceneBounds); } @@ -174,7 +168,7 @@ extern "C" OPENPGL_DLLEXPORT pgl_box3f pglFieldGetSceneBounds(PGLField field) return bounds; } -extern "C" OPENPGL_DLLEXPORT void pglFieldUpdate(PGLField field, PGLSampleStorage sampleStorage)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT void pglFieldUpdate(PGLField field, PGLSampleStorage sampleStorage) OPENPGL_CATCH_BEGIN { auto *gField = (IGuidingField *)field; auto *gSampleStorage = (openpgl::SampleDataStorage *)sampleStorage; @@ -182,8 +176,7 @@ extern "C" OPENPGL_DLLEXPORT void pglFieldUpdate(PGLField field, PGLSampleStora } OPENPGL_CATCH_END_VOID - -extern "C" OPENPGL_DLLEXPORT void pglFieldUpdateSurface(PGLField field, PGLSampleStorage sampleStorage)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT void pglFieldUpdateSurface(PGLField field, PGLSampleStorage sampleStorage) OPENPGL_CATCH_BEGIN { auto *gField = (IGuidingField *)field; auto *gSampleStorage = (openpgl::SampleDataStorage *)sampleStorage; @@ -191,7 +184,7 @@ extern "C" OPENPGL_DLLEXPORT void pglFieldUpdateSurface(PGLField field, PGLSamp } OPENPGL_CATCH_END_VOID -extern "C" OPENPGL_DLLEXPORT void pglFieldUpdateVolume(PGLField field, PGLSampleStorage sampleStorage)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT void pglFieldUpdateVolume(PGLField field, PGLSampleStorage sampleStorage) OPENPGL_CATCH_BEGIN { auto *gField = (IGuidingField *)field; auto *gSampleStorage = (openpgl::SampleDataStorage *)sampleStorage; @@ -199,46 +192,47 @@ extern "C" OPENPGL_DLLEXPORT void pglFieldUpdateVolume(PGLField field, PGLSampl } OPENPGL_CATCH_END_VOID - -extern "C" OPENPGL_DLLEXPORT void pglFieldReset(PGLField field)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT void pglFieldReset(PGLField field) OPENPGL_CATCH_BEGIN { auto *gField = (IGuidingField *)field; gField->resetField(); } OPENPGL_CATCH_END_VOID -extern "C" OPENPGL_DLLEXPORT PGLSurfaceSamplingDistribution pglFieldNewSurfaceSamplingDistribution(PGLField field)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT PGLSurfaceSamplingDistribution pglFieldNewSurfaceSamplingDistribution(PGLField field) OPENPGL_CATCH_BEGIN { auto *gField = (IGuidingField *)field; - ISurfaceSamplingDistribution* surfaceSamplingDistribution = gField->newSurfaceSamplingDistribution(); - return (PGLSurfaceSamplingDistribution) surfaceSamplingDistribution; + ISurfaceSamplingDistribution *surfaceSamplingDistribution = gField->newSurfaceSamplingDistribution(); + return (PGLSurfaceSamplingDistribution)surfaceSamplingDistribution; } OPENPGL_CATCH_END(nullptr) -extern "C" OPENPGL_DLLEXPORT bool pglFieldInitSurfaceSamplingDistribution(PGLField field, PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_point3f position, float* sample1D) +extern "C" OPENPGL_DLLEXPORT bool pglFieldInitSurfaceSamplingDistribution(PGLField field, PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_point3f position, + float *sample1D) { const openpgl::Point3 pos(position.x, position.y, position.z); auto *gField = (IGuidingField *)field; - ISurfaceSamplingDistribution* gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution*)surfaceSamplingDistribution; + ISurfaceSamplingDistribution *gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution *)surfaceSamplingDistribution; return gField->initSurfaceSamplingDistribution(gSurfaceSamplingDistribution, pos, sample1D); } -extern "C" OPENPGL_DLLEXPORT PGLVolumeSamplingDistribution pglFieldNewVolumeSamplingDistribution(PGLField field)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT PGLVolumeSamplingDistribution pglFieldNewVolumeSamplingDistribution(PGLField field) OPENPGL_CATCH_BEGIN { auto *gField = (IGuidingField *)field; - IVolumeSamplingDistribution* volumeSamplingDistribution = gField->newVolumeSamplingDistribution(); - return (PGLVolumeSamplingDistribution) volumeSamplingDistribution; + IVolumeSamplingDistribution *volumeSamplingDistribution = gField->newVolumeSamplingDistribution(); + return (PGLVolumeSamplingDistribution)volumeSamplingDistribution; } OPENPGL_CATCH_END(nullptr) -extern "C" OPENPGL_DLLEXPORT bool pglFieldInitVolumeSamplingDistribution(PGLField field, PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_point3f position, float* sample1D) +extern "C" OPENPGL_DLLEXPORT bool pglFieldInitVolumeSamplingDistribution(PGLField field, PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_point3f position, + float *sample1D) { const openpgl::Point3 pos(position.x, position.y, position.z); auto *gField = (IGuidingField *)field; - IVolumeSamplingDistribution* gVolumeSamplingDistribution = (IVolumeSamplingDistribution*)volumeSamplingDistribution; + IVolumeSamplingDistribution *gVolumeSamplingDistribution = (IVolumeSamplingDistribution *)volumeSamplingDistribution; return gField->initVolumeSamplingDistribution(gVolumeSamplingDistribution, pos, sample1D); } -extern "C" OPENPGL_DLLEXPORT bool pglFieldValidate(PGLField field) +extern "C" OPENPGL_DLLEXPORT bool pglFieldValidate(PGLField field) { const auto *gField = (const IGuidingField *)field; return gField->validate(true, true); @@ -269,13 +263,13 @@ extern "C" OPENPGL_DLLEXPORT PGLFieldStatistics pglFieldGetVolumeStatistics(PGLF #define OPENPGL_SAMPLE_STORAGE_STRING "OPENPGL_" OPENPGL_VERSION_STRING "_SAMPLE_STORAGE" -extern "C" OPENPGL_DLLEXPORT PGLSampleStorage pglNewSampleStorage()OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT PGLSampleStorage pglNewSampleStorage() OPENPGL_CATCH_BEGIN { - return (PGLSampleStorage) SampleDataStorage::newSampleDataStorage(); + return (PGLSampleStorage)SampleDataStorage::newSampleDataStorage(); } OPENPGL_CATCH_END(nullptr) -extern "C" OPENPGL_DLLEXPORT PGLSampleStorage pglNewSampleStorageFromFile(const char* sampleStorageFileName)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT PGLSampleStorage pglNewSampleStorageFromFile(const char *sampleStorageFileName) OPENPGL_CATCH_BEGIN { THROW_IF_NULL_STRING(sampleStorageFileName); return (PGLSampleStorage)openpgl::SampleDataStorage::newSampleDataStorageFromFile(sampleStorageFileName); @@ -288,7 +282,7 @@ extern "C" OPENPGL_DLLEXPORT void pglReleaseSampleStorage(PGLSampleStorage sampl delete gSampleStorage; } -extern "C" OPENPGL_DLLEXPORT bool pglSampleStorageStoreToFile(PGLSampleStorage sampleStorage, const char* sampleStorageFileName)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT bool pglSampleStorageStoreToFile(PGLSampleStorage sampleStorage, const char *sampleStorageFileName) OPENPGL_CATCH_BEGIN { THROW_IF_NULL_OBJECT(sampleStorage); THROW_IF_NULL_STRING(sampleStorageFileName); @@ -297,34 +291,34 @@ extern "C" OPENPGL_DLLEXPORT bool pglSampleStorageStoreToFile(PGLSampleStorage s } OPENPGL_CATCH_END(false) -extern "C" OPENPGL_DLLEXPORT void pglSampleStorageAddSample(PGLSampleStorage sampleStorage, const PGLSampleData& sample) +extern "C" OPENPGL_DLLEXPORT void pglSampleStorageAddSample(PGLSampleStorage sampleStorage, const PGLSampleData &sample) { auto *gSampleStorage = (openpgl::SampleDataStorage *)sampleStorage; - openpgl::SampleData opglSample = /**(openpgl::SampleData*)*/sample; + openpgl::SampleData opglSample = /**(openpgl::SampleData*)*/ sample; gSampleStorage->addSample(opglSample); } -extern "C" OPENPGL_DLLEXPORT void pglSampleStorageAddSamples(PGLSampleStorage sampleStorage, const PGLSampleData* samples, size_t numSamples) +extern "C" OPENPGL_DLLEXPORT void pglSampleStorageAddSamples(PGLSampleStorage sampleStorage, const PGLSampleData *samples, size_t numSamples) { auto *gSampleStorage = (openpgl::SampleDataStorage *)sampleStorage; - openpgl::SampleData* opglSamples = (openpgl::SampleData*)samples; - gSampleStorage->addSamples(opglSamples, numSamples); + openpgl::SampleData *opglSamples = (openpgl::SampleData *)samples; + gSampleStorage->addSamples(opglSamples, numSamples); } -extern "C" OPENPGL_DLLEXPORT void pglSampleStorageAddZeroValueSample(PGLSampleStorage sampleStorage, const PGLZeroValueSampleData& sample) +extern "C" OPENPGL_DLLEXPORT void pglSampleStorageAddZeroValueSample(PGLSampleStorage sampleStorage, const PGLZeroValueSampleData &sample) { auto *gSampleStorage = (openpgl::SampleDataStorage *)sampleStorage; - openpgl::ZeroValueSampleData opglSample = /**(openpgl::SampleData*)*/sample; + openpgl::ZeroValueSampleData opglSample = /**(openpgl::SampleData*)*/ sample; gSampleStorage->addZeroValueSample(opglSample); } -extern "C" OPENPGL_DLLEXPORT void pglSampleStorageAddZeroValueSamples(PGLSampleStorage sampleStorage, const PGLZeroValueSampleData* samples, size_t numSamples) +extern "C" OPENPGL_DLLEXPORT void pglSampleStorageAddZeroValueSamples(PGLSampleStorage sampleStorage, const PGLZeroValueSampleData *samples, size_t numSamples) { auto *gSampleStorage = (openpgl::SampleDataStorage *)sampleStorage; - openpgl::ZeroValueSampleData* opglSamples = (openpgl::ZeroValueSampleData*)samples; - gSampleStorage->addZeroValueSamples(opglSamples, numSamples); + openpgl::ZeroValueSampleData *opglSamples = (openpgl::ZeroValueSampleData *)samples; + gSampleStorage->addZeroValueSamples(opglSamples, numSamples); } extern "C" OPENPGL_DLLEXPORT void pglSampleStorageReserve(PGLSampleStorage sampleStorage, const size_t sizeSurface, const size_t sizeVolume) @@ -345,7 +339,6 @@ extern "C" OPENPGL_DLLEXPORT void pglSampleStorageClear(PGLSampleStorage sampleS gSampleStorage->clearInvalidSurface(); gSampleStorage->clearInvalidVolume(); - } extern "C" OPENPGL_DLLEXPORT void pglSampleStorageClearSurface(PGLSampleStorage sampleStorage) @@ -413,14 +406,14 @@ extern "C" OPENPGL_DLLEXPORT bool pglSampleStorageCompare(PGLSampleStorage sampl // PathSegmentStorage ///////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -extern "C" OPENPGL_DLLEXPORT PGLPathSegmentStorage pglNewPathSegmentStorage(bool trackZeroValueSamples)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT PGLPathSegmentStorage pglNewPathSegmentStorage(bool trackZeroValueSamples) OPENPGL_CATCH_BEGIN { - openpgl::PathSegmentDataStorage* pathSegmentStorage = new openpgl::PathSegmentDataStorage(trackZeroValueSamples); - return (PGLPathSegmentStorage) pathSegmentStorage; + openpgl::PathSegmentDataStorage *pathSegmentStorage = new openpgl::PathSegmentDataStorage(trackZeroValueSamples); + return (PGLPathSegmentStorage)pathSegmentStorage; } OPENPGL_CATCH_END(nullptr) -extern "C" OPENPGL_DLLEXPORT void pglReleasePathSegmentStorage(PGLPathSegmentStorage pathSegmentStorage)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT void pglReleasePathSegmentStorage(PGLPathSegmentStorage pathSegmentStorage) OPENPGL_CATCH_BEGIN { auto *gPathSegmentStorage = (openpgl::PathSegmentDataStorage *)pathSegmentStorage; delete gPathSegmentStorage; @@ -463,7 +456,8 @@ extern "C" OPENPGL_DLLEXPORT int pglPathSegmentGetNumSamples(PGLPathSegmentStora return gPathSegmentStorage->getNumSamples(); } -extern "C" OPENPGL_DLLEXPORT size_t pglPathSegmentStoragePrepareSamples(PGLPathSegmentStorage pathSegmentStorage, const bool useNEEMiWeights, const bool guideDirectLight, const bool rrAffectsDirectContribution) +extern "C" OPENPGL_DLLEXPORT size_t pglPathSegmentStoragePrepareSamples(PGLPathSegmentStorage pathSegmentStorage, const bool useNEEMiWeights, const bool guideDirectLight, + const bool rrAffectsDirectContribution) { auto *gPathSegmentStorage = (openpgl::PathSegmentDataStorage *)pathSegmentStorage; return gPathSegmentStorage->prepareSamples(useNEEMiWeights, guideDirectLight, rrAffectsDirectContribution); @@ -475,12 +469,12 @@ extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglPathSegmentStorageCalculatePixelEstima return gPathSegmentStorage->calculatePixelEstimate(rrAffectsDirectContribution); } -extern "C" OPENPGL_DLLEXPORT const PGLSampleData* pglPathSegmentStorageGetSamples(PGLPathSegmentStorage pathSegmentStorage, size_t &nSamples) +extern "C" OPENPGL_DLLEXPORT const PGLSampleData *pglPathSegmentStorageGetSamples(PGLPathSegmentStorage pathSegmentStorage, size_t &nSamples) { auto *gPathSegmentStorage = (openpgl::PathSegmentDataStorage *)pathSegmentStorage; - const openpgl::SampleData* opglSamples = gPathSegmentStorage->getSamples(); + const openpgl::SampleData *opglSamples = gPathSegmentStorage->getSamples(); nSamples = gPathSegmentStorage->getNumSamples(); - return (PGLSampleData*)opglSamples; + return (PGLSampleData *)opglSamples; } extern "C" OPENPGL_DLLEXPORT int pglPathSegmentGetNumZeroValueSamples(PGLPathSegmentStorage pathSegmentStorage) @@ -489,12 +483,12 @@ extern "C" OPENPGL_DLLEXPORT int pglPathSegmentGetNumZeroValueSamples(PGLPathSeg return gPathSegmentStorage->getNumZeroValueSamples(); } -extern "C" OPENPGL_DLLEXPORT const PGLZeroValueSampleData* pglPathSegmentStorageGetZeroValueSamples(PGLPathSegmentStorage pathSegmentStorage, size_t &nSamples) +extern "C" OPENPGL_DLLEXPORT const PGLZeroValueSampleData *pglPathSegmentStorageGetZeroValueSamples(PGLPathSegmentStorage pathSegmentStorage, size_t &nSamples) { auto *gPathSegmentStorage = (openpgl::PathSegmentDataStorage *)pathSegmentStorage; - const openpgl::ZeroValueSampleData* opglSamples = gPathSegmentStorage->getZeroValueSamples(); + const openpgl::ZeroValueSampleData *opglSamples = gPathSegmentStorage->getZeroValueSamples(); nSamples = gPathSegmentStorage->getNumZeroValueSamples(); - return (PGLZeroValueSampleData*)opglSamples; + return (PGLZeroValueSampleData *)opglSamples; } extern "C" OPENPGL_DLLEXPORT void pglPathSegmentStorageAddSample(PGLPathSegmentStorage pathSegmentStorage, PGLSampleData sample) @@ -503,10 +497,10 @@ extern "C" OPENPGL_DLLEXPORT void pglPathSegmentStorageAddSample(PGLPathSegmentS gPathSegmentStorage->addSample(sample); } -extern "C" OPENPGL_DLLEXPORT PGLPathSegmentData* pglPathSegmentStorageNextSegment(PGLPathSegmentStorage pathSegmentStorage) +extern "C" OPENPGL_DLLEXPORT PGLPathSegmentData *pglPathSegmentStorageNextSegment(PGLPathSegmentStorage pathSegmentStorage) { auto *gPathSegmentStorage = (openpgl::PathSegmentDataStorage *)pathSegmentStorage; - return (PGLPathSegmentData*)gPathSegmentStorage->next(); + return (PGLPathSegmentData *)gPathSegmentStorage->next(); } extern "C" OPENPGL_DLLEXPORT void pglPathSegmentStorageAddSegment(PGLPathSegmentStorage pathSegmentStorage, PGLPathSegmentData segment) @@ -519,17 +513,16 @@ extern "C" OPENPGL_DLLEXPORT bool pglPathSegmentStorageValidateSamples(PGLPathSe { auto *gPathSegmentStorage = (openpgl::PathSegmentDataStorage *)pathSegmentStorage; return gPathSegmentStorage->validateSamples(); - } extern "C" OPENPGL_DLLEXPORT bool pglPathSegmentStorageValidateSegments(PGLPathSegmentStorage pathSegmentStorage) { auto *gPathSegmentStorage = (openpgl::PathSegmentDataStorage *)pathSegmentStorage; return gPathSegmentStorage->validateSegments(); - } -extern "C" OPENPGL_DLLEXPORT void pglPathSegmentStoragePropagateSamples(PGLPathSegmentStorage pathSegmentStorage, PGLSampleStorage sampleStorage, bool guideDirectLight, bool useNEEMiWeights, bool rrAffectsDirectContribution) +extern "C" OPENPGL_DLLEXPORT void pglPathSegmentStoragePropagateSamples(PGLPathSegmentStorage pathSegmentStorage, PGLSampleStorage sampleStorage, bool guideDirectLight, + bool useNEEMiWeights, bool rrAffectsDirectContribution) { auto *gPathSegmentStorage = (openpgl::PathSegmentDataStorage *)pathSegmentStorage; auto *gSampleStorage = (openpgl::SampleDataStorage *)sampleStorage; @@ -540,29 +533,29 @@ extern "C" OPENPGL_DLLEXPORT void pglPathSegmentStoragePropagateSamples(PGLPathS // Distribution ///// ///////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -extern "C" OPENPGL_DLLEXPORT void pglReleaseSurfaceSamplingDistribution(PGLSurfaceSamplingDistribution surfaceSamplingDistribution)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT void pglReleaseSurfaceSamplingDistribution(PGLSurfaceSamplingDistribution surfaceSamplingDistribution) OPENPGL_CATCH_BEGIN { - ISurfaceSamplingDistribution* gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution*)surfaceSamplingDistribution; + ISurfaceSamplingDistribution *gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution *)surfaceSamplingDistribution; delete gSurfaceSamplingDistribution; } OPENPGL_CATCH_END_VOID extern "C" OPENPGL_DLLEXPORT void pglSurfaceSamplingDistributionApplyCosineProduct(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f normal) { - ISurfaceSamplingDistribution* gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution*)surfaceSamplingDistribution; + ISurfaceSamplingDistribution *gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution *)surfaceSamplingDistribution; openpgl::Vector3 opglNormal(normal.x, normal.y, normal.z); gSurfaceSamplingDistribution->applyCosineProduct(opglNormal); } extern "C" OPENPGL_DLLEXPORT bool pglSurfaceSamplingDistributionSupportsApplyCosineProduct(PGLSurfaceSamplingDistribution surfaceSamplingDistribution) { - ISurfaceSamplingDistribution* gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution*)surfaceSamplingDistribution; + ISurfaceSamplingDistribution *gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution *)surfaceSamplingDistribution; return gSurfaceSamplingDistribution->supportsApplyCosineProduct(); } extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglSurfaceSamplingDistributionSample(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_point2f sample) { - ISurfaceSamplingDistribution* gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution*)surfaceSamplingDistribution; + ISurfaceSamplingDistribution *gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution *)surfaceSamplingDistribution; openpgl::Point2 opglSample(sample.x, sample.y); openpgl::Vector3 opglDirection = gSurfaceSamplingDistribution->sample(opglSample); pgl_vec3f pglDirection; @@ -572,13 +565,13 @@ extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglSurfaceSamplingDistributionSample(PGLS extern "C" OPENPGL_DLLEXPORT float pglSurfaceSamplingDistributionPDF(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f direction) { - ISurfaceSamplingDistribution* gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution*)surfaceSamplingDistribution; + ISurfaceSamplingDistribution *gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution *)surfaceSamplingDistribution; return gSurfaceSamplingDistribution->pdf(openpgl::Vector3(direction.x, direction.y, direction.z)); } extern "C" OPENPGL_DLLEXPORT float pglSurfaceSamplingDistributionSamplePDF(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_point2f sample, pgl_vec3f &direction) { - ISurfaceSamplingDistribution* gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution*)surfaceSamplingDistribution; + ISurfaceSamplingDistribution *gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution *)surfaceSamplingDistribution; openpgl::Vector3 dir; float pdf = gSurfaceSamplingDistribution->samplePdf({sample.x, sample.y}, dir); direction = {dir.x, dir.y, dir.z}; @@ -587,39 +580,40 @@ extern "C" OPENPGL_DLLEXPORT float pglSurfaceSamplingDistributionSamplePDF(PGLSu extern "C" OPENPGL_DLLEXPORT float pglSurfaceSamplingDistributionIncomingRadiancePDF(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f direction) { - ISurfaceSamplingDistribution* gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution*)surfaceSamplingDistribution; + ISurfaceSamplingDistribution *gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution *)surfaceSamplingDistribution; return gSurfaceSamplingDistribution->pdfLi(openpgl::Vector3(direction.x, direction.y, direction.z)); } extern "C" OPENPGL_DLLEXPORT uint32_t pglSurfaceSamplingDistributionGetId(PGLSurfaceSamplingDistribution surfaceSamplingDistribution) { - ISurfaceSamplingDistribution* gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution*)surfaceSamplingDistribution; + ISurfaceSamplingDistribution *gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution *)surfaceSamplingDistribution; return gSurfaceSamplingDistribution->getId(); } extern "C" OPENPGL_DLLEXPORT bool pglSurfaceSamplingDistributionValidate(PGLSurfaceSamplingDistribution surfaceSamplingDistribution) { - ISurfaceSamplingDistribution* gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution*)surfaceSamplingDistribution; + ISurfaceSamplingDistribution *gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution *)surfaceSamplingDistribution; return gSurfaceSamplingDistribution->validate(); } extern "C" OPENPGL_DLLEXPORT void pglSurfaceSamplingDistributionClear(PGLSurfaceSamplingDistribution surfaceSamplingDistribution) { - ISurfaceSamplingDistribution* gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution*)surfaceSamplingDistribution; + ISurfaceSamplingDistribution *gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution *)surfaceSamplingDistribution; gSurfaceSamplingDistribution->clear(); } extern "C" OPENPGL_DLLEXPORT PGLRegion pglSurfaceSamplingGetRegion(PGLSurfaceSamplingDistribution surfaceSamplingDistribution) { - ISurfaceSamplingDistribution* gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution*)surfaceSamplingDistribution; - const IRegion* gRegion = gSurfaceSamplingDistribution->getRegion(); - return (PGLRegion) gRegion; + ISurfaceSamplingDistribution *gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution *)surfaceSamplingDistribution; + const IRegion *gRegion = gSurfaceSamplingDistribution->getRegion(); + return (PGLRegion)gRegion; } #ifdef OPENPGL_RADIANCE_CACHES -extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglSurfaceSamplingDistributionIncomingRadiance(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f direction, const bool directLightMIS) +extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglSurfaceSamplingDistributionIncomingRadiance(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f direction, + const bool directLightMIS) { - ISurfaceSamplingDistribution* gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution*)surfaceSamplingDistribution; + ISurfaceSamplingDistribution *gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution *)surfaceSamplingDistribution; openpgl::Vector3 incomingRadiance = gSurfaceSamplingDistribution->incomingRadiance(openpgl::Vector3(direction.x, direction.y, direction.z), directLightMIS); pgl_vec3f pglIncomingRadiance; @@ -629,7 +623,7 @@ extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglSurfaceSamplingDistributionIncomingRad extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglSurfaceSamplingDistributionOutgoingRadiance(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f direction) { - ISurfaceSamplingDistribution* gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution*)surfaceSamplingDistribution; + ISurfaceSamplingDistribution *gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution *)surfaceSamplingDistribution; openpgl::Vector3 outgoingRadiance = gSurfaceSamplingDistribution->outgoingRadiance(openpgl::Vector3(direction.x, direction.y, direction.z)); pgl_vec3f pglOutgoingRadiance; @@ -637,9 +631,10 @@ extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglSurfaceSamplingDistributionOutgoingRad return pglOutgoingRadiance; } -extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglSurfaceSamplingDistributionIrradiance(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f normal, const bool directLightMIS) +extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglSurfaceSamplingDistributionIrradiance(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f normal, + const bool directLightMIS) { - ISurfaceSamplingDistribution* gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution*)surfaceSamplingDistribution; + ISurfaceSamplingDistribution *gSurfaceSamplingDistribution = (ISurfaceSamplingDistribution *)surfaceSamplingDistribution; openpgl::Vector3 irradiance = gSurfaceSamplingDistribution->irradiance(openpgl::Vector3(normal.x, normal.y, normal.z), directLightMIS); pgl_vec3f pglIrradiance; @@ -649,16 +644,16 @@ extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglSurfaceSamplingDistributionIrradiance( #endif -extern "C" OPENPGL_DLLEXPORT void pglReleaseVolumeSamplingDistribution(PGLVolumeSamplingDistribution volumeSamplingDistribution)OPENPGL_CATCH_BEGIN +extern "C" OPENPGL_DLLEXPORT void pglReleaseVolumeSamplingDistribution(PGLVolumeSamplingDistribution volumeSamplingDistribution) OPENPGL_CATCH_BEGIN { - IVolumeSamplingDistribution* gVolumeSamplingDistribution = (IVolumeSamplingDistribution*)volumeSamplingDistribution; + IVolumeSamplingDistribution *gVolumeSamplingDistribution = (IVolumeSamplingDistribution *)volumeSamplingDistribution; delete gVolumeSamplingDistribution; } OPENPGL_CATCH_END_VOID extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglVolumeSamplingDistributionSample(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_point2f sample) { - IVolumeSamplingDistribution* gVolumeSamplingDistribution = (IVolumeSamplingDistribution*)volumeSamplingDistribution; + IVolumeSamplingDistribution *gVolumeSamplingDistribution = (IVolumeSamplingDistribution *)volumeSamplingDistribution; openpgl::Point2 opglSample(sample.x, sample.y); openpgl::Vector3 opglDirection = gVolumeSamplingDistribution->sample(opglSample); pgl_vec3f pglDirection; @@ -668,13 +663,13 @@ extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglVolumeSamplingDistributionSample(PGLVo extern "C" OPENPGL_DLLEXPORT float pglVolumeSamplingDistributionPDF(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_vec3f direction) { - IVolumeSamplingDistribution* gVolumeSamplingDistribution = (IVolumeSamplingDistribution*)volumeSamplingDistribution; + IVolumeSamplingDistribution *gVolumeSamplingDistribution = (IVolumeSamplingDistribution *)volumeSamplingDistribution; return gVolumeSamplingDistribution->pdf(openpgl::Vector3(direction.x, direction.y, direction.z)); } extern "C" OPENPGL_DLLEXPORT float pglVolumeSamplingDistributionSamplePDF(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_point2f sample, pgl_vec3f &direction) { - IVolumeSamplingDistribution* gVolumeSamplingDistribution = (IVolumeSamplingDistribution*)volumeSamplingDistribution; + IVolumeSamplingDistribution *gVolumeSamplingDistribution = (IVolumeSamplingDistribution *)volumeSamplingDistribution; openpgl::Vector3 dir; float pdf = gVolumeSamplingDistribution->samplePdf({sample.x, sample.y}, dir); direction = {dir.x, dir.y, dir.z}; @@ -683,45 +678,47 @@ extern "C" OPENPGL_DLLEXPORT float pglVolumeSamplingDistributionSamplePDF(PGLVol extern "C" OPENPGL_DLLEXPORT float pglVolumeSamplingDistributionIncomingRadiancePDF(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_vec3f direction) { - IVolumeSamplingDistribution* gVolumeSamplingDistribution = (IVolumeSamplingDistribution*)volumeSamplingDistribution; + IVolumeSamplingDistribution *gVolumeSamplingDistribution = (IVolumeSamplingDistribution *)volumeSamplingDistribution; return gVolumeSamplingDistribution->pdfLi(openpgl::Vector3(direction.x, direction.y, direction.z)); } extern "C" OPENPGL_DLLEXPORT uint32_t pglVolumeSamplingDistributionGetId(PGLVolumeSamplingDistribution volumeSamplingDistribution) { - IVolumeSamplingDistribution* gVolumeSamplingDistribution = (IVolumeSamplingDistribution*)volumeSamplingDistribution; + IVolumeSamplingDistribution *gVolumeSamplingDistribution = (IVolumeSamplingDistribution *)volumeSamplingDistribution; return gVolumeSamplingDistribution->getId(); } extern "C" OPENPGL_DLLEXPORT bool pglVolumeSamplingDistributionValidate(PGLVolumeSamplingDistribution volumeSamplingDistribution) { - IVolumeSamplingDistribution* gVolumeSamplingDistribution = (IVolumeSamplingDistribution*)volumeSamplingDistribution; + IVolumeSamplingDistribution *gVolumeSamplingDistribution = (IVolumeSamplingDistribution *)volumeSamplingDistribution; return gVolumeSamplingDistribution->validate(); } extern "C" OPENPGL_DLLEXPORT void pglVolumeSamplingDistributionClear(PGLVolumeSamplingDistribution volumeSamplingDistribution) { - IVolumeSamplingDistribution* gVolumeSamplingDistribution = (IVolumeSamplingDistribution*)volumeSamplingDistribution; + IVolumeSamplingDistribution *gVolumeSamplingDistribution = (IVolumeSamplingDistribution *)volumeSamplingDistribution; gVolumeSamplingDistribution->clear(); } -extern "C" OPENPGL_DLLEXPORT void pglVolumeSamplingDistributionApplySingleLobeHenyeyGreensteinProduct(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_vec3f dir, const float meanCosine) +extern "C" OPENPGL_DLLEXPORT void pglVolumeSamplingDistributionApplySingleLobeHenyeyGreensteinProduct(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_vec3f dir, + const float meanCosine) { - IVolumeSamplingDistribution* gVolumeSamplingDistribution = (IVolumeSamplingDistribution*)volumeSamplingDistribution; + IVolumeSamplingDistribution *gVolumeSamplingDistribution = (IVolumeSamplingDistribution *)volumeSamplingDistribution; openpgl::Vector3 opglDir(dir.x, dir.y, dir.z); gVolumeSamplingDistribution->applySingleLobeHenyeyGreensteinProduct(opglDir, meanCosine); } extern "C" OPENPGL_DLLEXPORT bool pglVolumeSamplingDistributionSupportsApplySingleLobeHenyeyGreensteinProduct(PGLVolumeSamplingDistribution volumeSamplingDistribution) { - IVolumeSamplingDistribution* gVolumeSamplingDistribution = (IVolumeSamplingDistribution*)volumeSamplingDistribution; + IVolumeSamplingDistribution *gVolumeSamplingDistribution = (IVolumeSamplingDistribution *)volumeSamplingDistribution; return gVolumeSamplingDistribution->supportsApplySingleLobeHenyeyGreensteinProduct(); } #ifdef OPENPGL_RADIANCE_CACHES -extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglVolumeSamplingDistributionIncomingRadiance(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_vec3f direction, const bool directLightMIS) +extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglVolumeSamplingDistributionIncomingRadiance(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_vec3f direction, + const bool directLightMIS) { - IVolumeSamplingDistribution* gVolumeSamplingDistribution = (IVolumeSamplingDistribution*)volumeSamplingDistribution; + IVolumeSamplingDistribution *gVolumeSamplingDistribution = (IVolumeSamplingDistribution *)volumeSamplingDistribution; openpgl::Vector3 incomingRadiance = gVolumeSamplingDistribution->incomingRadiance(openpgl::Vector3(direction.x, direction.y, direction.z), directLightMIS); pgl_vec3f pglIncomingRadiance; @@ -731,7 +728,7 @@ extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglVolumeSamplingDistributionIncomingRadi extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglVolumeSamplingDistributionOutgoingRadiance(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_vec3f direction) { - IVolumeSamplingDistribution* gVolumeSamplingDistribution = (IVolumeSamplingDistribution*)volumeSamplingDistribution; + IVolumeSamplingDistribution *gVolumeSamplingDistribution = (IVolumeSamplingDistribution *)volumeSamplingDistribution; openpgl::Vector3 outgoingRadiance = gVolumeSamplingDistribution->outgoingRadiance(openpgl::Vector3(direction.x, direction.y, direction.z)); pgl_vec3f pglOutgoingRadiance; @@ -739,9 +736,10 @@ extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglVolumeSamplingDistributionOutgoingRadi return pglOutgoingRadiance; } -extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglVolumeSamplingDistributionInscatteredRadiance(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_vec3f direction, float g, const bool directLightMIS) +extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglVolumeSamplingDistributionInscatteredRadiance(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_vec3f direction, float g, + const bool directLightMIS) { - IVolumeSamplingDistribution* gVolumeSamplingDistribution = (IVolumeSamplingDistribution*)volumeSamplingDistribution; + IVolumeSamplingDistribution *gVolumeSamplingDistribution = (IVolumeSamplingDistribution *)volumeSamplingDistribution; openpgl::Vector3 inscatteredRadiance = gVolumeSamplingDistribution->inScatteredRadiance(openpgl::Vector3(direction.x, direction.y, direction.z), g, directLightMIS); pgl_vec3f pglInscatteredRadiance; @@ -751,7 +749,7 @@ extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglVolumeSamplingDistributionInscatteredR extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglVolumeSamplingDistributionFluence(PGLVolumeSamplingDistribution volumeSamplingDistribution, const bool directLightMIS) { - IVolumeSamplingDistribution* gVolumeSamplingDistribution = (IVolumeSamplingDistribution*)volumeSamplingDistribution; + IVolumeSamplingDistribution *gVolumeSamplingDistribution = (IVolumeSamplingDistribution *)volumeSamplingDistribution; openpgl::Vector3 fluence = gVolumeSamplingDistribution->fluence(directLightMIS); pgl_vec3f pglFluence; @@ -761,38 +759,38 @@ extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglVolumeSamplingDistributionFluence(PGLV #endif -extern "C" OPENPGL_DLLEXPORT void pglFieldArgumentsSetDefaults(PGLFieldArguments &fieldArguments, const PGL_SPATIAL_STRUCTURE_TYPE spatialType, const PGL_DIRECTIONAL_DISTRIBUTION_TYPE directionalType, const bool deterministic, const size_t maxSamplesPerLeaf) +extern "C" OPENPGL_DLLEXPORT void pglFieldArgumentsSetDefaults(PGLFieldArguments &fieldArguments, const PGL_SPATIAL_STRUCTURE_TYPE spatialType, + const PGL_DIRECTIONAL_DISTRIBUTION_TYPE directionalType, const bool deterministic, const size_t maxSamplesPerLeaf) { switch (spatialType) { - default: - case PGL_SPATIAL_STRUCTURE_TYPE::PGL_SPATIAL_STRUCTURE_KDTREE: - fieldArguments.spatialStructureType = PGL_SPATIAL_STRUCTURE_KDTREE; - fieldArguments.spatialSturctureArguments = new PGLKDTreeArguments(); - reinterpret_cast(fieldArguments.spatialSturctureArguments)->maxSamples = maxSamplesPerLeaf; - break; + default: + case PGL_SPATIAL_STRUCTURE_TYPE::PGL_SPATIAL_STRUCTURE_KDTREE: + fieldArguments.spatialStructureType = PGL_SPATIAL_STRUCTURE_KDTREE; + fieldArguments.spatialSturctureArguments = new PGLKDTreeArguments(); + reinterpret_cast(fieldArguments.spatialSturctureArguments)->maxSamples = maxSamplesPerLeaf; + break; } fieldArguments.deterministic = deterministic; fieldArguments.debugArguments.fitRegions = true; - + switch (directionalType) { - default: - case PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_PARALLAX_AWARE_VMM: - fieldArguments.directionalDistributionType = PGL_DIRECTIONAL_DISTRIBUTION_PARALLAX_AWARE_VMM; - fieldArguments.directionalDistributionArguments = new PGLVMMFactoryArguments(maxSamplesPerLeaf); - break; - case PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_QUADTREE: - fieldArguments.directionalDistributionType = PGL_DIRECTIONAL_DISTRIBUTION_QUADTREE; - fieldArguments.directionalDistributionArguments = new PGLDQTFactoryArguments(); - break; - case PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_VMM: - fieldArguments.directionalDistributionType = PGL_DIRECTIONAL_DISTRIBUTION_VMM; - fieldArguments.directionalDistributionArguments = new PGLVMMFactoryArguments(maxSamplesPerLeaf); - break; + default: + case PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_PARALLAX_AWARE_VMM: + fieldArguments.directionalDistributionType = PGL_DIRECTIONAL_DISTRIBUTION_PARALLAX_AWARE_VMM; + fieldArguments.directionalDistributionArguments = new PGLVMMFactoryArguments(maxSamplesPerLeaf); + break; + case PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_QUADTREE: + fieldArguments.directionalDistributionType = PGL_DIRECTIONAL_DISTRIBUTION_QUADTREE; + fieldArguments.directionalDistributionArguments = new PGLDQTFactoryArguments(); + break; + case PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_VMM: + fieldArguments.directionalDistributionType = PGL_DIRECTIONAL_DISTRIBUTION_VMM; + fieldArguments.directionalDistributionArguments = new PGLVMMFactoryArguments(maxSamplesPerLeaf); + break; } - } /////////////////////////////////////////////////////////////////////////////// @@ -803,7 +801,6 @@ extern "C" OPENPGL_DLLEXPORT void pglReleaseFieldStatistics(PGLFieldStatistics f { auto *gFieldStatistics = (openpgl::FieldStatistics *)fieldStatistics; delete gFieldStatistics; - } extern "C" OPENPGL_DLLEXPORT PGLString pglFieldStatisticsToString(PGLFieldStatistics fieldStatistics) @@ -811,7 +808,7 @@ extern "C" OPENPGL_DLLEXPORT PGLString pglFieldStatisticsToString(PGLFieldStatis auto *gFieldStatistics = (openpgl::FieldStatistics *)fieldStatistics; std::string str = gFieldStatistics->toString(); PGLString pglStr; - pglStr.m_size = str.length()+1; + pglStr.m_size = str.length() + 1; pglStr.m_str = new char[pglStr.m_size]; strcpy(pglStr.m_str, str.c_str()); return pglStr; @@ -822,7 +819,7 @@ extern "C" OPENPGL_DLLEXPORT PGLString pglFieldStatisticsHeaderCSVString(PGLFiel auto *gFieldStatistics = (openpgl::FieldStatistics *)fieldStatistics; std::string str = gFieldStatistics->headerCSVString(); PGLString pglStr; - pglStr.m_size = str.length()+1; + pglStr.m_size = str.length() + 1; pglStr.m_str = new char[pglStr.m_size]; strcpy(pglStr.m_str, str.c_str()); return pglStr; @@ -833,13 +830,12 @@ extern "C" OPENPGL_DLLEXPORT PGLString pglFieldStatisticsToCSVString(PGLFieldSta auto *gFieldStatistics = (openpgl::FieldStatistics *)fieldStatistics; std::string str = gFieldStatistics->toCSVString(); PGLString pglStr; - pglStr.m_size = str.length()+1; + pglStr.m_size = str.length() + 1; pglStr.m_str = new char[pglStr.m_size]; strcpy(pglStr.m_str, str.c_str()); return pglStr; } - /////////////////////////////////////////////////////////////////////////////// // String ///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// @@ -854,59 +850,58 @@ extern "C" OPENPGL_DLLEXPORT void pglReleaseString(PGLString str) } } - #if defined(OPENPGL_IMAGE_SPACE_GUIDING_BUFFER) /////////////////////////////////////////////////////////////////////////////// // ImageSpaceGuidingBuffer /////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -extern "C" OPENPGL_DLLEXPORT PGLImageSpaceGuidingBuffer pglFieldNewImageSpaceGuidingBuffer(const pgl_point2i resolution) +extern "C" OPENPGL_DLLEXPORT PGLImageSpaceGuidingBuffer pglFieldNewImageSpaceGuidingBuffer(const pgl_point2i resolution) { - return (PGLImageSpaceGuidingBuffer) new openpgl::ImageSpaceGuidingBuffer(resolution, false); + return (PGLImageSpaceGuidingBuffer) new openpgl::ImageSpaceGuidingBuffer(resolution, false); } -extern "C" OPENPGL_DLLEXPORT PGLImageSpaceGuidingBuffer pglFieldNewImageSpaceGuidingBufferFromFile(const char* fileName) +extern "C" OPENPGL_DLLEXPORT PGLImageSpaceGuidingBuffer pglFieldNewImageSpaceGuidingBufferFromFile(const char *fileName) { return (PGLImageSpaceGuidingBuffer) new openpgl::ImageSpaceGuidingBuffer(fileName); } -extern "C" OPENPGL_DLLEXPORT void pglReleaseImageSpaceGuidingBuffer(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer) +extern "C" OPENPGL_DLLEXPORT void pglReleaseImageSpaceGuidingBuffer(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer) { auto *gImageSpaceGuidingBuffer = (openpgl::ImageSpaceGuidingBuffer *)imageSpaceGuidingBuffer; delete gImageSpaceGuidingBuffer; } -extern "C" OPENPGL_DLLEXPORT void pglImageSpaceGuidingBufferUpdate(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer) +extern "C" OPENPGL_DLLEXPORT void pglImageSpaceGuidingBufferUpdate(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer) { auto *gImageSpaceGuidingBuffer = (openpgl::ImageSpaceGuidingBuffer *)imageSpaceGuidingBuffer; gImageSpaceGuidingBuffer->update(); } -extern "C" OPENPGL_DLLEXPORT void pglImageSpaceGuidingBufferAddSample(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer, const pgl_point2i pixel, const PGLImageSpaceSample sample) +extern "C" OPENPGL_DLLEXPORT void pglImageSpaceGuidingBufferAddSample(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer, const pgl_point2i pixel, const PGLImageSpaceSample sample) { auto *gImageSpaceGuidingBuffer = (openpgl::ImageSpaceGuidingBuffer *)imageSpaceGuidingBuffer; gImageSpaceGuidingBuffer->addSample(pixel, sample); } -extern "C" OPENPGL_DLLEXPORT void pglImageSpaceGuidingBufferStore(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer, const char* fileName) +extern "C" OPENPGL_DLLEXPORT void pglImageSpaceGuidingBufferStore(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer, const char *fileName) { auto *gImageSpaceGuidingBuffer = (openpgl::ImageSpaceGuidingBuffer *)imageSpaceGuidingBuffer; gImageSpaceGuidingBuffer->store(fileName); } -extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglImageSpaceGuidingBufferGetPixelContributionEstimate(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer, const pgl_point2i pixel) +extern "C" OPENPGL_DLLEXPORT pgl_vec3f pglImageSpaceGuidingBufferGetPixelContributionEstimate(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer, const pgl_point2i pixel) { auto *gImageSpaceGuidingBuffer = (openpgl::ImageSpaceGuidingBuffer *)imageSpaceGuidingBuffer; return gImageSpaceGuidingBuffer->getContributionEstimate(pixel); } -extern "C" OPENPGL_DLLEXPORT bool pglImageSpaceGuidingBufferIsReady(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer) +extern "C" OPENPGL_DLLEXPORT bool pglImageSpaceGuidingBufferIsReady(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer) { auto *gImageSpaceGuidingBuffer = (openpgl::ImageSpaceGuidingBuffer *)imageSpaceGuidingBuffer; return gImageSpaceGuidingBuffer->isReady(); } -extern "C" OPENPGL_DLLEXPORT void pglImageSpaceGuidingBufferReset(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer) +extern "C" OPENPGL_DLLEXPORT void pglImageSpaceGuidingBufferReset(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer) { auto *gImageSpaceGuidingBuffer = (openpgl::ImageSpaceGuidingBuffer *)imageSpaceGuidingBuffer; gImageSpaceGuidingBuffer->reset(); diff --git a/openpgl/api/deviceCPU16.cpp b/openpgl/api/deviceCPU16.cpp index 9312656..f148b9a 100644 --- a/openpgl/api/deviceCPU16.cpp +++ b/openpgl/api/deviceCPU16.cpp @@ -1,9 +1,11 @@ #include "device/Device.h" -namespace openpgl { +namespace openpgl +{ -IDevice* newDeviceCPU16(size_t numThreads) { - return (IDevice*) new Device<16>(numThreads); +IDevice *newDeviceCPU16(size_t numThreads) +{ + return (IDevice *)new Device<16>(numThreads); } -} \ No newline at end of file +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/api/deviceCPU4.cpp b/openpgl/api/deviceCPU4.cpp index a08a32d..2503297 100644 --- a/openpgl/api/deviceCPU4.cpp +++ b/openpgl/api/deviceCPU4.cpp @@ -1,9 +1,11 @@ #include "device/Device.h" -namespace openpgl { +namespace openpgl +{ -IDevice* newDeviceCPU4(size_t numThreads) { - return (IDevice*) new Device<4>(numThreads); +IDevice *newDeviceCPU4(size_t numThreads) +{ + return (IDevice *)new Device<4>(numThreads); } -} \ No newline at end of file +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/api/deviceCPU8.cpp b/openpgl/api/deviceCPU8.cpp index 0d72ff6..9f23f25 100644 --- a/openpgl/api/deviceCPU8.cpp +++ b/openpgl/api/deviceCPU8.cpp @@ -1,9 +1,11 @@ #include "device/Device.h" -namespace openpgl { +namespace openpgl +{ -IDevice* newDeviceCPU8(size_t numThreads) { - return (IDevice*) new Device<8>(numThreads); +IDevice *newDeviceCPU8(size_t numThreads) +{ + return (IDevice *)new Device<8>(numThreads); } -} \ No newline at end of file +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/data/PathSegmentData.h b/openpgl/data/PathSegmentData.h index c396f7f..27a161e 100644 --- a/openpgl/data/PathSegmentData.h +++ b/openpgl/data/PathSegmentData.h @@ -3,130 +3,130 @@ #pragma once -#include "../openpgl_common.h" -#include "../include/openpgl/data.h" - #include +#include "../include/openpgl/data.h" +#include "../openpgl_common.h" + namespace openpgl { inline float OPENPGL_SPECTRUM_TO_FLOAT(Vector3 spectrum) { - //return (spectrum[0] + spectrum[1] + spectrum[2] ) / 3.0f; + // return (spectrum[0] + spectrum[1] + spectrum[2] ) / 3.0f; return std::max(spectrum[0], std::max(spectrum[1], spectrum[2])); } using PathSegmentData = PGLPathSegmentData; -inline bool isValid(const PathSegmentData& psd) - { - bool valid = true; - valid = valid && embree::isvalid(psd.position.x); - valid = valid && embree::isvalid(psd.position.y); - valid = valid && embree::isvalid(psd.position.z); - OPENPGL_ASSERT(valid); - - valid = valid && embree::isvalid(psd.directionIn.x); - valid = valid && psd.directionIn.x <= 1.0f && psd.directionIn.x >= -1.0f; - valid = valid && embree::isvalid(psd.directionIn.y); - valid = valid && psd.directionIn.y <= 1.0f && psd.directionIn.y >= -1.0f; - valid = valid && embree::isvalid(psd.directionIn.z); - valid = valid && psd.directionIn.z <= 1.0f && psd.directionIn.z >= -1.0f; - OPENPGL_ASSERT(valid); - - valid = valid && embree::isvalid(psd.directionOut.x); - valid = valid && psd.directionOut.x <= 1.0f && psd.directionOut.x >= -1.0f; - valid = valid && embree::isvalid(psd.directionOut.y); - valid = valid && psd.directionOut.y <= 1.0f && psd.directionOut.y >= -1.0f; - valid = valid && embree::isvalid(psd.directionOut.z); - valid = valid && psd.directionOut.z <= 1.0f && psd.directionOut.z >= -1.0f; - OPENPGL_ASSERT(valid); - - valid = valid && embree::isvalid(psd.normal.x); - valid = valid && psd.normal.x <= 1.0f && psd.normal.x >= -1.0f; - valid = valid && embree::isvalid(psd.normal.y); - valid = valid && psd.normal.y <= 1.0f && psd.normal.y >= -1.0f; - valid = valid && embree::isvalid(psd.normal.z); - valid = valid && psd.normal.z <= 1.0f && psd.normal.z >= -1.0f; - OPENPGL_ASSERT(valid); - - valid = valid && embree::isvalid(psd.pdfDirectionIn); - valid = valid && psd.pdfDirectionIn >=0.f; - OPENPGL_ASSERT(valid); - - valid = valid && embree::isvalid(psd.scatteringWeight.x); - valid = valid && psd.scatteringWeight.x >= 0.0f; - valid = valid && embree::isvalid(psd.scatteringWeight.y); - valid = valid && psd.scatteringWeight.y >= 0.0f; - valid = valid && embree::isvalid(psd.scatteringWeight.z); - valid = valid && psd.scatteringWeight.z >= 0.0f; - OPENPGL_ASSERT(valid); - - valid = valid && embree::isvalid(psd.transmittanceWeight.x); - valid = valid && psd.transmittanceWeight.x >= 0.0f; - valid = valid && embree::isvalid(psd.transmittanceWeight.y); - valid = valid && psd.transmittanceWeight.y >= 0.0f; - valid = valid && embree::isvalid(psd.transmittanceWeight.z); - valid = valid && psd.transmittanceWeight.z >= 0.0f; - OPENPGL_ASSERT(valid); - - valid = valid && embree::isvalid(psd.directContribution.x); - valid = valid && psd.directContribution.x >= 0.0f; - valid = valid && embree::isvalid(psd.directContribution.y); - valid = valid && psd.directContribution.y >= 0.0f; - valid = valid && embree::isvalid(psd.directContribution.z); - valid = valid && psd.directContribution.z >= 0.0f; - OPENPGL_ASSERT(valid); - - valid = valid && embree::isvalid(psd.scatteredContribution.x); - valid = valid && psd.scatteredContribution.x >= 0.0f; - valid = valid && embree::isvalid(psd.scatteredContribution.y); - valid = valid && psd.scatteredContribution.y >= 0.0f; - valid = valid && embree::isvalid(psd.scatteredContribution.z); - valid = valid && psd.scatteredContribution.z >= 0.0f; - OPENPGL_ASSERT(valid); - - valid = valid && embree::isvalid(psd.miWeight); - valid = valid && psd.miWeight >=0.f && psd.miWeight <=1.0f; - OPENPGL_ASSERT(valid); - - valid = valid && embree::isvalid(psd.russianRouletteSurvivalProbability); - valid = valid && psd.miWeight >=0.f && psd.russianRouletteSurvivalProbability <=1.0f; - OPENPGL_ASSERT(valid); - - valid = valid && embree::isvalid(psd.eta); - valid = valid && psd.eta >=0.f; - OPENPGL_ASSERT(valid); - - valid = valid && embree::isvalid(psd.roughness); - valid = valid && psd.roughness >=0.f && psd.roughness <=1.f; - OPENPGL_ASSERT(valid); - - return valid; - } - - std::string toString(const PGLPathSegmentData& psd) - { - std::stringstream ss; - ss << "PathSegmentData: "; - ss << "pos = " << psd.position.x << "\t " << psd.position.y << "\t " << psd.position.z << "\t "; - ss << "\t dirIn = " << psd.directionIn.x << "\t " << psd.directionIn.y << "\t " << psd.directionIn.z << "\t "; - ss << "\t dirOut = " << psd.directionOut.x << "\t " << psd.directionOut.y << "\t " << psd.directionOut.z << "\t "; - ss << "\t normal = " << psd.normal.x << "\t " << psd.normal.y << "\t " << psd.normal.z << "\t "; - ss << "\t volume = " << psd.volumeScatter; - ss << "\t pdf = " << psd.pdfDirectionIn; - ss << "\t delta = " << psd.isDelta; - ss << "\t scatteringWeight = " << psd.scatteringWeight.x << "\t " << psd.scatteringWeight.y << "\t " << psd.scatteringWeight.z << "\t "; - ss << "\t transmittanceWeight = " << psd.transmittanceWeight.x << "\t " << psd.transmittanceWeight.y << "\t " << psd.transmittanceWeight.z << "\t "; - ss << "\t directContribution = " << psd.directContribution.x << "\t " << psd.directContribution.y << "\t " << psd.directContribution.z << "\t "; - ss << "\t miWeight = " << psd.miWeight; - ss << "\t scatteredContribution = " << psd.scatteredContribution.x << "\t " << psd.scatteredContribution.y << "\t " << psd.scatteredContribution.z << "\t "; - ss << "\t russianRouletteSurvivalProbability = " << psd.russianRouletteSurvivalProbability; - ss << "\t eta = " << psd.eta; - ss << "\t rough = " << psd.roughness; - ss << std::endl; - - return ss.str(); - } -} \ No newline at end of file +inline bool isValid(const PathSegmentData &psd) +{ + bool valid = true; + valid = valid && embree::isvalid(psd.position.x); + valid = valid && embree::isvalid(psd.position.y); + valid = valid && embree::isvalid(psd.position.z); + OPENPGL_ASSERT(valid); + + valid = valid && embree::isvalid(psd.directionIn.x); + valid = valid && psd.directionIn.x <= 1.0f && psd.directionIn.x >= -1.0f; + valid = valid && embree::isvalid(psd.directionIn.y); + valid = valid && psd.directionIn.y <= 1.0f && psd.directionIn.y >= -1.0f; + valid = valid && embree::isvalid(psd.directionIn.z); + valid = valid && psd.directionIn.z <= 1.0f && psd.directionIn.z >= -1.0f; + OPENPGL_ASSERT(valid); + + valid = valid && embree::isvalid(psd.directionOut.x); + valid = valid && psd.directionOut.x <= 1.0f && psd.directionOut.x >= -1.0f; + valid = valid && embree::isvalid(psd.directionOut.y); + valid = valid && psd.directionOut.y <= 1.0f && psd.directionOut.y >= -1.0f; + valid = valid && embree::isvalid(psd.directionOut.z); + valid = valid && psd.directionOut.z <= 1.0f && psd.directionOut.z >= -1.0f; + OPENPGL_ASSERT(valid); + + valid = valid && embree::isvalid(psd.normal.x); + valid = valid && psd.normal.x <= 1.0f && psd.normal.x >= -1.0f; + valid = valid && embree::isvalid(psd.normal.y); + valid = valid && psd.normal.y <= 1.0f && psd.normal.y >= -1.0f; + valid = valid && embree::isvalid(psd.normal.z); + valid = valid && psd.normal.z <= 1.0f && psd.normal.z >= -1.0f; + OPENPGL_ASSERT(valid); + + valid = valid && embree::isvalid(psd.pdfDirectionIn); + valid = valid && psd.pdfDirectionIn >= 0.f; + OPENPGL_ASSERT(valid); + + valid = valid && embree::isvalid(psd.scatteringWeight.x); + valid = valid && psd.scatteringWeight.x >= 0.0f; + valid = valid && embree::isvalid(psd.scatteringWeight.y); + valid = valid && psd.scatteringWeight.y >= 0.0f; + valid = valid && embree::isvalid(psd.scatteringWeight.z); + valid = valid && psd.scatteringWeight.z >= 0.0f; + OPENPGL_ASSERT(valid); + + valid = valid && embree::isvalid(psd.transmittanceWeight.x); + valid = valid && psd.transmittanceWeight.x >= 0.0f; + valid = valid && embree::isvalid(psd.transmittanceWeight.y); + valid = valid && psd.transmittanceWeight.y >= 0.0f; + valid = valid && embree::isvalid(psd.transmittanceWeight.z); + valid = valid && psd.transmittanceWeight.z >= 0.0f; + OPENPGL_ASSERT(valid); + + valid = valid && embree::isvalid(psd.directContribution.x); + valid = valid && psd.directContribution.x >= 0.0f; + valid = valid && embree::isvalid(psd.directContribution.y); + valid = valid && psd.directContribution.y >= 0.0f; + valid = valid && embree::isvalid(psd.directContribution.z); + valid = valid && psd.directContribution.z >= 0.0f; + OPENPGL_ASSERT(valid); + + valid = valid && embree::isvalid(psd.scatteredContribution.x); + valid = valid && psd.scatteredContribution.x >= 0.0f; + valid = valid && embree::isvalid(psd.scatteredContribution.y); + valid = valid && psd.scatteredContribution.y >= 0.0f; + valid = valid && embree::isvalid(psd.scatteredContribution.z); + valid = valid && psd.scatteredContribution.z >= 0.0f; + OPENPGL_ASSERT(valid); + + valid = valid && embree::isvalid(psd.miWeight); + valid = valid && psd.miWeight >= 0.f && psd.miWeight <= 1.0f; + OPENPGL_ASSERT(valid); + + valid = valid && embree::isvalid(psd.russianRouletteSurvivalProbability); + valid = valid && psd.miWeight >= 0.f && psd.russianRouletteSurvivalProbability <= 1.0f; + OPENPGL_ASSERT(valid); + + valid = valid && embree::isvalid(psd.eta); + valid = valid && psd.eta >= 0.f; + OPENPGL_ASSERT(valid); + + valid = valid && embree::isvalid(psd.roughness); + valid = valid && psd.roughness >= 0.f && psd.roughness <= 1.f; + OPENPGL_ASSERT(valid); + + return valid; +} + +std::string toString(const PGLPathSegmentData &psd) +{ + std::stringstream ss; + ss << "PathSegmentData: "; + ss << "pos = " << psd.position.x << "\t " << psd.position.y << "\t " << psd.position.z << "\t "; + ss << "\t dirIn = " << psd.directionIn.x << "\t " << psd.directionIn.y << "\t " << psd.directionIn.z << "\t "; + ss << "\t dirOut = " << psd.directionOut.x << "\t " << psd.directionOut.y << "\t " << psd.directionOut.z << "\t "; + ss << "\t normal = " << psd.normal.x << "\t " << psd.normal.y << "\t " << psd.normal.z << "\t "; + ss << "\t volume = " << psd.volumeScatter; + ss << "\t pdf = " << psd.pdfDirectionIn; + ss << "\t delta = " << psd.isDelta; + ss << "\t scatteringWeight = " << psd.scatteringWeight.x << "\t " << psd.scatteringWeight.y << "\t " << psd.scatteringWeight.z << "\t "; + ss << "\t transmittanceWeight = " << psd.transmittanceWeight.x << "\t " << psd.transmittanceWeight.y << "\t " << psd.transmittanceWeight.z << "\t "; + ss << "\t directContribution = " << psd.directContribution.x << "\t " << psd.directContribution.y << "\t " << psd.directContribution.z << "\t "; + ss << "\t miWeight = " << psd.miWeight; + ss << "\t scatteredContribution = " << psd.scatteredContribution.x << "\t " << psd.scatteredContribution.y << "\t " << psd.scatteredContribution.z << "\t "; + ss << "\t russianRouletteSurvivalProbability = " << psd.russianRouletteSurvivalProbability; + ss << "\t eta = " << psd.eta; + ss << "\t rough = " << psd.roughness; + ss << std::endl; + + return ss.str(); +} +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/data/PathSegmentDataStorage.h b/openpgl/data/PathSegmentDataStorage.h index 50cebef..d56eb02 100644 --- a/openpgl/data/PathSegmentDataStorage.h +++ b/openpgl/data/PathSegmentDataStorage.h @@ -3,82 +3,84 @@ #pragma once -#include "../openpgl_common.h" #include "../include/openpgl/compression.h" +#include "../openpgl_common.h" +#include "../spatial/Region.h" #include "PathSegmentData.h" #include "SampleData.h" -#include "../spatial/Region.h" #include "SampleDataStorage.h" -#define OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY +#define OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY namespace openpgl { struct PathSegmentDataStorage { - PathSegmentDataStorage(bool trackZeroValueSamples = false){ + PathSegmentDataStorage(bool trackZeroValueSamples = false) + { m_track_zero_value_samples = trackZeroValueSamples; } - PathSegmentDataStorage(const PathSegmentDataStorage&) = delete; + PathSegmentDataStorage(const PathSegmentDataStorage &) = delete; - PathSegmentDataStorage & operator=(const PathSegmentDataStorage&) = delete; + PathSegmentDataStorage &operator=(const PathSegmentDataStorage &) = delete; - ~PathSegmentDataStorage(){ + ~PathSegmentDataStorage() + { #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - if(m_segmentStorage) + if (m_segmentStorage) delete[] m_segmentStorage; - if(m_sampleStorage) + if (m_sampleStorage) delete[] m_sampleStorage; - if(m_zeroValueSampleStorage) + if (m_zeroValueSampleStorage) delete[] m_zeroValueSampleStorage; #endif }; -private: + private: float m_max_distance = {1e6f}; -#if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - PathSegmentData* m_segmentStorage {nullptr}; +#if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) + PathSegmentData *m_segmentStorage{nullptr}; int m_seg_idx = {-1}; int m_max_seg_size = {0}; - SampleData* m_sampleStorage {nullptr}; + SampleData *m_sampleStorage{nullptr}; int m_sample_idx = {-1}; int m_max_sample_size = {0}; - bool m_track_zero_value_samples {false}; - ZeroValueSampleData* m_zeroValueSampleStorage {nullptr}; + bool m_track_zero_value_samples{false}; + ZeroValueSampleData *m_zeroValueSampleStorage{nullptr}; int m_zero_value_sample_idx = {-1}; int m_max_zero_value_sample_size = {0}; #else - std::vector m_segmentStorage; + std::vector m_segmentStorage; std::vector m_sampleStorage; std::vector m_zeroValueSampleStorage; #endif -public: + public: void reserve(const size_t &size) { #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - if(m_max_sample_size == size) + if (m_max_sample_size == size) return; - if(m_segmentStorage) + if (m_segmentStorage) delete[] m_segmentStorage; m_segmentStorage = new PathSegmentData[size]; m_seg_idx = -1; m_max_seg_size = size; - if(m_sampleStorage) + if (m_sampleStorage) delete[] m_sampleStorage; m_sampleStorage = new SampleData[size]; m_sample_idx = -1; m_max_sample_size = size; - if(m_zeroValueSampleStorage) + if (m_zeroValueSampleStorage) delete[] m_zeroValueSampleStorage; m_zeroValueSampleStorage = new ZeroValueSampleData[size]; @@ -86,7 +88,7 @@ struct PathSegmentDataStorage m_max_zero_value_sample_size = size; #else - if(m_segmentStorage.size() == size) + if (m_segmentStorage.size() == size) return; m_segmentStorage.reserve(size); m_sampleStorage.reserve(size); @@ -97,7 +99,7 @@ struct PathSegmentDataStorage size_t size() { #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - return m_seg_idx+1; + return m_seg_idx + 1; #else return m_segmentStorage.size(); #endif @@ -106,41 +108,43 @@ struct PathSegmentDataStorage void clear() { #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - //std::cout << "PathSegmentDataStorage::clear: " << std::endl; + // std::cout << "PathSegmentDataStorage::clear: " << std::endl; m_seg_idx = -1; m_sample_idx = -1; m_zero_value_sample_idx = -1; #else - //m_segmentStorage.clear(); - //m_sampleStorage.clear(); + // m_segmentStorage.clear(); + // m_sampleStorage.clear(); m_segmentStorage.resize(0); m_sampleStorage.resize(0); m_zeroValueSampleStorage.resize(0); -#endif +#endif } PathSegmentData *next() { #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - if(m_seg_idx + 1 <= m_max_seg_size) + if (m_seg_idx + 1 <= m_max_seg_size) { m_seg_idx++; m_segmentStorage[m_seg_idx] = PathSegmentData(); return &m_segmentStorage[m_seg_idx]; - } else { - //std::cout << "PathSegmentDataStorage::next: idx = " << m_seg_idx << "max_size = " << m_max_seg_size << std::endl; + } + else + { + // std::cout << "PathSegmentDataStorage::next: idx = " << m_seg_idx << "max_size = " << m_max_seg_size << std::endl; return nullptr; } #else - m_segmentStorage.emplace_back(); - return &m_segmentStorage.back(); + m_segmentStorage.emplace_back(); + return &m_segmentStorage.back(); #endif } - void addSegment(const PGLPathSegmentData& segment) + void addSegment(const PGLPathSegmentData &segment) { #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - if(m_seg_idx+1 <= m_max_seg_size) + if (m_seg_idx + 1 <= m_max_seg_size) { m_seg_idx++; m_segmentStorage[m_seg_idx] = segment; @@ -153,7 +157,7 @@ struct PathSegmentDataStorage void push_back(const PathSegmentData &psData) { #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - if(m_seg_idx+1 <= m_max_seg_size) + if (m_seg_idx + 1 <= m_max_seg_size) { m_seg_idx++; m_segmentStorage[m_seg_idx] = psData; @@ -163,7 +167,7 @@ struct PathSegmentDataStorage #endif } - float getMaxDistance() const + float getMaxDistance() const { return m_max_distance; } @@ -184,42 +188,45 @@ struct PathSegmentDataStorage size_t prepareSamples(const bool useNEEMiWeights = false, const bool guideDirectLight = false, const bool rrAffectsDirectContribution = true) { - // clamping thresholds to avoid generating extremly strong fireflies that - // could mess-up the fitting of the distributions - const float minPDF {0.01f}; - const openpgl::Vector3 maxThroughput {10.0f}; + // clamping thresholds to avoid generating extremly strong fireflies that + // could mess-up the fitting of the distributions + const float minPDF{0.01f}; + const openpgl::Vector3 maxThroughput{10.0f}; #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - size_t numSegments = m_seg_idx+1; + size_t numSegments = m_seg_idx + 1; #else size_t numSegments = m_segmentStorage.size(); #endif float lastDistance = 0.0f; // go revese from the start vertex of the last path segment (the end vertex of 2nd last segment) - // towards the vertex of the first path segment - for (int i=numSegments-2; i>=0; --i) + // towards the vertex of the first path segment + for (int i = numSegments - 2; i >= 0; --i) { const openpgl::PathSegmentData ¤tPathSegment = m_segmentStorage[i]; - float currentDistance = embree::length(openpgl::Point3(m_segmentStorage[i+1].position.x, m_segmentStorage[i+1].position.y, m_segmentStorage[i+1].position.z) - openpgl::Point3(currentPathSegment.position.x, currentPathSegment.position.y, currentPathSegment.position.z)); - // calcualte the distance to the source + float currentDistance = embree::length(openpgl::Point3(m_segmentStorage[i + 1].position.x, m_segmentStorage[i + 1].position.y, m_segmentStorage[i + 1].position.z) - + openpgl::Point3(currentPathSegment.position.x, currentPathSegment.position.y, currentPathSegment.position.z)); + // calcualte the distance to the source float distance = std::fmin(currentDistance + lastDistance, 2.0f * m_max_distance); ////// Calculating/updating the distance to the source of the incident radiance for the next vertex // if the current vertex is not a delta intercation or rough we reset the previous distacne // TODO: double check the roughness threshold at some point - if(!currentPathSegment.isDelta && currentPathSegment.roughness >=0.3f) + if (!currentPathSegment.isDelta && currentPathSegment.roughness >= 0.3f) { lastDistance = 0.0f; } // else if the curent vetex is a dirac/delta interaction update the previous distance - else + else { lastDistance = distance; - if(currentPathSegment.eta!= 1.0f) + if (currentPathSegment.eta != 1.0f) { - float cosThetaI = embree::dot(openpgl::Vector3(currentPathSegment.normal.x, currentPathSegment.normal.y, currentPathSegment.normal.z), openpgl::Vector3(currentPathSegment.directionOut.x, currentPathSegment.directionOut.y, currentPathSegment.directionOut.z)); - float cosThetaO = embree::dot(openpgl::Vector3(currentPathSegment.normal.x, currentPathSegment.normal.y, currentPathSegment.normal.z), openpgl::Vector3(currentPathSegment.directionIn.x, currentPathSegment.directionIn.y, currentPathSegment.directionIn.z)); - lastDistance *= std::fabs(cosThetaI/(cosThetaO*currentPathSegment.eta)); + float cosThetaI = embree::dot(openpgl::Vector3(currentPathSegment.normal.x, currentPathSegment.normal.y, currentPathSegment.normal.z), + openpgl::Vector3(currentPathSegment.directionOut.x, currentPathSegment.directionOut.y, currentPathSegment.directionOut.z)); + float cosThetaO = embree::dot(openpgl::Vector3(currentPathSegment.normal.x, currentPathSegment.normal.y, currentPathSegment.normal.z), + openpgl::Vector3(currentPathSegment.directionIn.x, currentPathSegment.directionIn.y, currentPathSegment.directionIn.z)); + lastDistance *= std::fabs(cosThetaI / (cosThetaO * currentPathSegment.eta)); } } @@ -227,69 +234,78 @@ struct PathSegmentDataStorage // using a non-direct (delta) sampling method if (!currentPathSegment.isDelta && currentPathSegment.roughness > 0.01f) { - // prepare the current pos, direction, distance, pdf at the current // path vertex openpgl::Point3 pos = openpgl::Point3(currentPathSegment.position.x, currentPathSegment.position.y, currentPathSegment.position.z); // using the direction directly is numerically more stable than recalcuating - // it using position of the next segment when the distance is small. + // it using position of the next segment when the distance is small. openpgl::Vector3 dir = openpgl::Vector3(currentPathSegment.directionIn.x, currentPathSegment.directionIn.y, currentPathSegment.directionIn.z); #ifdef OPENPGL_RADIANCE_CACHES openpgl::Vector3 dirOut = openpgl::Vector3(currentPathSegment.directionOut.x, currentPathSegment.directionOut.y, currentPathSegment.directionOut.z); - openpgl::Vector3 scatteringWeight = openpgl::Vector3(currentPathSegment.scatteringWeight.x, currentPathSegment.scatteringWeight.y,currentPathSegment.scatteringWeight.z); - openpgl::Vector3 scatteredContribution = openpgl::Vector3(currentPathSegment.scatteredContribution.x, currentPathSegment.scatteredContribution.y,currentPathSegment.scatteredContribution.z); - openpgl::Vector3 directContribution = openpgl::Vector3(currentPathSegment.directContribution.x, currentPathSegment.directContribution.y,currentPathSegment.directContribution.z); + openpgl::Vector3 scatteringWeight = + openpgl::Vector3(currentPathSegment.scatteringWeight.x, currentPathSegment.scatteringWeight.y, currentPathSegment.scatteringWeight.z); + openpgl::Vector3 scatteredContribution = + openpgl::Vector3(currentPathSegment.scatteredContribution.x, currentPathSegment.scatteredContribution.y, currentPathSegment.scatteredContribution.z); + openpgl::Vector3 directContribution = + openpgl::Vector3(currentPathSegment.directContribution.x, currentPathSegment.directContribution.y, currentPathSegment.directContribution.z); #endif - float pdf = std::max(minPDF,currentPathSegment.pdfDirectionIn); + float pdf = std::max(minPDF, currentPathSegment.pdfDirectionIn); uint32_t flags{0}; bool insideVolume = currentPathSegment.volumeScatter; - if(insideVolume) + if (insideVolume) { flags |= SampleData::EInsideVolume; } - + bool directLightSample = false; float misWeight = 1.f; // evalaute the incident radiance the incident - openpgl::Vector3 throughput {1.0f}; - openpgl::Vector3 contribution {0.0f}; + openpgl::Vector3 throughput{1.0f}; + openpgl::Vector3 contribution{0.0f}; float previousRRSurvivalProb = 1.0f; - for (size_t j = i+1; j < numSegments; ++j) + for (size_t j = i + 1; j < numSegments; ++j) { const openpgl::PathSegmentData &nextPathSegment = m_segmentStorage[j]; - throughput = throughput * openpgl::Vector3(m_segmentStorage[j-1].transmittanceWeight.x, m_segmentStorage[j-1].transmittanceWeight.y, m_segmentStorage[j-1].transmittanceWeight.z); + throughput = throughput * openpgl::Vector3(m_segmentStorage[j - 1].transmittanceWeight.x, m_segmentStorage[j - 1].transmittanceWeight.y, + m_segmentStorage[j - 1].transmittanceWeight.z); OPENPGL_ASSERT(embree::isvalid(throughput)); OPENPGL_ASSERT(throughput[0] >= 0.f && throughput[1] >= 0.f && throughput[2] >= 0.f) openpgl::Vector3 clampedThroughput = embree::min(throughput, maxThroughput); - contribution += clampedThroughput * openpgl::Vector3(nextPathSegment.scatteredContribution.x, nextPathSegment.scatteredContribution.y, nextPathSegment.scatteredContribution.z); + contribution += clampedThroughput * + openpgl::Vector3(nextPathSegment.scatteredContribution.x, nextPathSegment.scatteredContribution.y, nextPathSegment.scatteredContribution.z); OPENPGL_ASSERT(embree::isvalid(contribution)); OPENPGL_ASSERT(contribution[0] >= 0.f && contribution[1] >= 0.f && contribution[2] >= 0.f); - - openpgl::Vector3 directContribution = openpgl::Vector3(nextPathSegment.directContribution.x, nextPathSegment.directContribution.y, nextPathSegment.directContribution.z); + + openpgl::Vector3 directContribution = + openpgl::Vector3(nextPathSegment.directContribution.x, nextPathSegment.directContribution.y, nextPathSegment.directContribution.z); // Todo: need explanation - if(!rrAffectsDirectContribution) + if (!rrAffectsDirectContribution) { directContribution *= previousRRSurvivalProb; } - if(directContribution[0] > 0.f || directContribution[1] > 0.f || directContribution[2] > 0.f){ - if(j == i+1) + if (directContribution[0] > 0.f || directContribution[1] > 0.f || directContribution[2] > 0.f) + { + if (j == i + 1) { - if(contribution[0] > 0.f || contribution[1] > 0.f || contribution[2] > 0.f){ + if (contribution[0] > 0.f || contribution[1] > 0.f || contribution[2] > 0.f) + { std::cout << "scateredContribution" << std::endl; - } else { + } + else + { directLightSample = true; } - if(guideDirectLight) + if (guideDirectLight) { - if(!useNEEMiWeights) + if (!useNEEMiWeights) { contribution += clampedThroughput * directContribution; OPENPGL_ASSERT(embree::isvalid(contribution)); OPENPGL_ASSERT(contribution[0] >= 0.f && contribution[1] >= 0.f && contribution[2] >= 0.f); - } - else + } + else { contribution += clampedThroughput * nextPathSegment.miWeight * directContribution; misWeight = nextPathSegment.miWeight; @@ -306,7 +322,7 @@ struct PathSegmentDataStorage } } throughput = throughput * openpgl::Vector3(nextPathSegment.scatteringWeight.x, nextPathSegment.scatteringWeight.y, nextPathSegment.scatteringWeight.z); - if(nextPathSegment.russianRouletteSurvivalProbability > 0.f) + if (nextPathSegment.russianRouletteSurvivalProbability > 0.f) { throughput /= nextPathSegment.russianRouletteSurvivalProbability; } @@ -319,18 +335,19 @@ struct PathSegmentDataStorage OPENPGL_ASSERT(embree::isvalid(throughput)); OPENPGL_ASSERT(throughput[0] >= 0.f && throughput[1] >= 0.f && throughput[2] >= 0.f) } - if(directLightSample) + if (directLightSample) { flags |= SampleData::EDirectLight; } - OPENPGL_ASSERT(embree::isvalid(contribution)); + OPENPGL_ASSERT(embree::isvalid(contribution)); OPENPGL_ASSERT(contribution[0] >= 0.f && contribution[1] >= 0.f && contribution[2] >= 0.f); - if (contribution[0] > 0.0f || contribution[1] > 0.0f || contribution[2] > 0.0f ) + if (contribution[0] > 0.0f || contribution[1] > 0.0f || contribution[2] > 0.0f) { OPENPGL_ASSERT(embree::isvalid(distance)); - if(distance>0){ - const float weight = OPENPGL_SPECTRUM_TO_FLOAT(contribution)/pdf; + if (distance > 0) + { + const float weight = OPENPGL_SPECTRUM_TO_FLOAT(contribution) / pdf; OPENPGL_ASSERT(embree::isvalid(weight)); OPENPGL_ASSERT(weight >= 0.f); SampleData dsd; @@ -343,9 +360,9 @@ struct PathSegmentDataStorage dsd.directionOut = pgl_directionOut; pgl_vec3f colorOut; - colorOut.x = /*directContribution.x*/ + scatteredContribution.x + scatteringWeight.x * contribution[0]; - colorOut.y = /*directContribution.y*/ + scatteredContribution.y + scatteringWeight.y * contribution[1]; - colorOut.z = /*directContribution.z*/ + scatteredContribution.z + scatteringWeight.z * contribution[2]; + colorOut.x = /*directContribution.x*/ +scatteredContribution.x + scatteringWeight.x * contribution[0]; + colorOut.y = /*directContribution.y*/ +scatteredContribution.y + scatteringWeight.y * contribution[1]; + colorOut.z = /*directContribution.z*/ +scatteredContribution.z + scatteringWeight.z * contribution[2]; dsd.radianceOut = colorOut; pgl_vec3f colorIn = {contribution[0], contribution[1], contribution[2]}; dsd.radianceIn = colorIn; @@ -355,7 +372,7 @@ struct PathSegmentDataStorage dsd.distance = distance; dsd.flags = flags; #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - if(m_sample_idx+1 <= m_max_sample_size) + if (m_sample_idx + 1 <= m_max_sample_size) { m_sample_idx++; m_sampleStorage[m_sample_idx] = dsd; @@ -365,7 +382,7 @@ struct PathSegmentDataStorage #endif } } - else if(m_track_zero_value_samples) + else if (m_track_zero_value_samples) { ZeroValueSampleData isd; isd.position = {pos[0], pos[1], pos[2]}; @@ -377,7 +394,7 @@ struct PathSegmentDataStorage #endif isd.volume = insideVolume; #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - if(m_zero_value_sample_idx+1 <= m_max_zero_value_sample_size) + if (m_zero_value_sample_idx + 1 <= m_max_zero_value_sample_size) { m_zero_value_sample_idx++; m_zeroValueSampleStorage[m_zero_value_sample_idx] = isd; @@ -386,12 +403,11 @@ struct PathSegmentDataStorage m_zeroValueSampleStorage.emplace_back(isd); #endif } - } } #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - return m_sample_idx+1; + return m_sample_idx + 1; #else return m_sampleStorage.size(); #endif @@ -399,9 +415,8 @@ struct PathSegmentDataStorage pgl_vec3f calculatePixelEstimate(const bool rrAffectsDirectContribution = true) { - #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - size_t numSegments = m_seg_idx+1; + size_t numSegments = m_seg_idx + 1; #else size_t numSegments = m_segmentStorage.size(); #endif @@ -411,27 +426,30 @@ struct PathSegmentDataStorage finalColor.y = 0.f; finalColor.z = 0.f; - if(numSegments==0) + if (numSegments == 0) return finalColor; - + // evalaute the incident radiance the incident - openpgl::Vector3 throughput {1.0f}; - openpgl::Vector3 contribution {0.0f}; + openpgl::Vector3 throughput{1.0f}; + openpgl::Vector3 contribution{0.0f}; float previousRRSurvivalProb = m_segmentStorage[0].russianRouletteSurvivalProbability; - for (size_t j = 0+1; j < numSegments; ++j) + for (size_t j = 0 + 1; j < numSegments; ++j) { const openpgl::PathSegmentData &nextPathSegment = m_segmentStorage[j]; - throughput = throughput * openpgl::Vector3(m_segmentStorage[j-1].transmittanceWeight.x, m_segmentStorage[j-1].transmittanceWeight.y, m_segmentStorage[j-1].transmittanceWeight.z); + throughput = throughput * openpgl::Vector3(m_segmentStorage[j - 1].transmittanceWeight.x, m_segmentStorage[j - 1].transmittanceWeight.y, + m_segmentStorage[j - 1].transmittanceWeight.z); OPENPGL_ASSERT(embree::isvalid(throughput)); OPENPGL_ASSERT(throughput[0] >= 0.f && throughput[1] >= 0.f && throughput[2] >= 0.f) - contribution += throughput * openpgl::Vector3(nextPathSegment.scatteredContribution.x, nextPathSegment.scatteredContribution.y, nextPathSegment.scatteredContribution.z); + contribution += + throughput * openpgl::Vector3(nextPathSegment.scatteredContribution.x, nextPathSegment.scatteredContribution.y, nextPathSegment.scatteredContribution.z); OPENPGL_ASSERT(embree::isvalid(contribution)); OPENPGL_ASSERT(contribution[0] >= 0.f && contribution[1] >= 0.f && contribution[2] >= 0.f); - openpgl::Vector3 directContribution = openpgl::Vector3(nextPathSegment.directContribution.x, nextPathSegment.directContribution.y, nextPathSegment.directContribution.z); - if(!rrAffectsDirectContribution) + openpgl::Vector3 directContribution = + openpgl::Vector3(nextPathSegment.directContribution.x, nextPathSegment.directContribution.y, nextPathSegment.directContribution.z); + if (!rrAffectsDirectContribution) { directContribution *= previousRRSurvivalProb; } @@ -440,7 +458,7 @@ struct PathSegmentDataStorage OPENPGL_ASSERT(contribution[0] >= 0.f && contribution[1] >= 0.f && contribution[2] >= 0.f); throughput = throughput * openpgl::Vector3(nextPathSegment.scatteringWeight.x, nextPathSegment.scatteringWeight.y, nextPathSegment.scatteringWeight.z); - if(nextPathSegment.russianRouletteSurvivalProbability > 0.f) + if (nextPathSegment.russianRouletteSurvivalProbability > 0.f) { throughput /= nextPathSegment.russianRouletteSurvivalProbability; } @@ -456,29 +474,39 @@ struct PathSegmentDataStorage OPENPGL_ASSERT(embree::isvalid(contribution)); OPENPGL_ASSERT(contribution[0] >= 0.f && contribution[1] >= 0.f && contribution[2] >= 0.f); - if(m_segmentStorage[0].russianRouletteSurvivalProbability > 0.f) + if (m_segmentStorage[0].russianRouletteSurvivalProbability > 0.f) { - finalColor.x = m_segmentStorage[0].directContribution.x + m_segmentStorage[0].scatteredContribution.x + m_segmentStorage[0].scatteringWeight.x /** m_segmentStorage[0].transmittanceWeight.x*/ * contribution[0] / m_segmentStorage[0].russianRouletteSurvivalProbability; - finalColor.y = m_segmentStorage[0].directContribution.y + m_segmentStorage[0].scatteredContribution.y + m_segmentStorage[0].scatteringWeight.y /** m_segmentStorage[0].transmittanceWeight.y*/ * contribution[1] / m_segmentStorage[0].russianRouletteSurvivalProbability; - finalColor.z = m_segmentStorage[0].directContribution.z + m_segmentStorage[0].scatteredContribution.z + m_segmentStorage[0].scatteringWeight.z /** m_segmentStorage[0].transmittanceWeight.z*/ * contribution[2] / m_segmentStorage[0].russianRouletteSurvivalProbability; - } else { - finalColor.x = m_segmentStorage[0].directContribution.x + m_segmentStorage[0].scatteredContribution.x + m_segmentStorage[0].scatteringWeight.x /** m_segmentStorage[0].transmittanceWeight.x*/ * contribution[0]; - finalColor.y = m_segmentStorage[0].directContribution.y + m_segmentStorage[0].scatteredContribution.y + m_segmentStorage[0].scatteringWeight.y /** m_segmentStorage[0].transmittanceWeight.y*/ * contribution[1]; - finalColor.z = m_segmentStorage[0].directContribution.z + m_segmentStorage[0].scatteredContribution.z + m_segmentStorage[0].scatteringWeight.z /** m_segmentStorage[0].transmittanceWeight.z*/ * contribution[2]; + finalColor.x = + m_segmentStorage[0].directContribution.x + m_segmentStorage[0].scatteredContribution.x + + m_segmentStorage[0].scatteringWeight.x /** m_segmentStorage[0].transmittanceWeight.x*/ * contribution[0] / m_segmentStorage[0].russianRouletteSurvivalProbability; + finalColor.y = + m_segmentStorage[0].directContribution.y + m_segmentStorage[0].scatteredContribution.y + + m_segmentStorage[0].scatteringWeight.y /** m_segmentStorage[0].transmittanceWeight.y*/ * contribution[1] / m_segmentStorage[0].russianRouletteSurvivalProbability; + finalColor.z = + m_segmentStorage[0].directContribution.z + m_segmentStorage[0].scatteredContribution.z + + m_segmentStorage[0].scatteringWeight.z /** m_segmentStorage[0].transmittanceWeight.z*/ * contribution[2] / m_segmentStorage[0].russianRouletteSurvivalProbability; + } + else + { + finalColor.x = m_segmentStorage[0].directContribution.x + m_segmentStorage[0].scatteredContribution.x + + m_segmentStorage[0].scatteringWeight.x /** m_segmentStorage[0].transmittanceWeight.x*/ * contribution[0]; + finalColor.y = m_segmentStorage[0].directContribution.y + m_segmentStorage[0].scatteredContribution.y + + m_segmentStorage[0].scatteringWeight.y /** m_segmentStorage[0].transmittanceWeight.y*/ * contribution[1]; + finalColor.z = m_segmentStorage[0].directContribution.z + m_segmentStorage[0].scatteredContribution.z + + m_segmentStorage[0].scatteringWeight.z /** m_segmentStorage[0].transmittanceWeight.z*/ * contribution[2]; } - - if(numSegments == 1) + if (numSegments == 1) { - finalColor.x = m_segmentStorage[0].directContribution.x + m_segmentStorage[0].scatteredContribution.x;// + currentPathSegment.scatteringWeight.x * contribution[0]; - finalColor.y = m_segmentStorage[0].directContribution.y + m_segmentStorage[0].scatteredContribution.y;// + currentPathSegment.scatteringWeight.y * contribution[1]; - finalColor.z = m_segmentStorage[0].directContribution.z + m_segmentStorage[0].scatteredContribution.z;// + currentPathSegment.scatteringWeight.z * contribution[2]; + finalColor.x = m_segmentStorage[0].directContribution.x + m_segmentStorage[0].scatteredContribution.x; // + currentPathSegment.scatteringWeight.x * contribution[0]; + finalColor.y = m_segmentStorage[0].directContribution.y + m_segmentStorage[0].scatteredContribution.y; // + currentPathSegment.scatteringWeight.y * contribution[1]; + finalColor.z = m_segmentStorage[0].directContribution.z + m_segmentStorage[0].scatteredContribution.z; // + currentPathSegment.scatteringWeight.z * contribution[2]; } return finalColor; } - const SampleData* getSamples()const + const SampleData *getSamples() const { #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) return m_sampleStorage; @@ -502,7 +530,7 @@ struct PathSegmentDataStorage OPENPGL_ASSERT(sampleData.distance > 0); OPENPGL_ASSERT(embree::isvalid(sampleData.distance)); #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - if(m_sample_idx+1 <= m_max_sample_size) + if (m_sample_idx + 1 <= m_max_sample_size) { m_sample_idx++; m_sampleStorage[m_sample_idx] = sampleData; @@ -520,7 +548,7 @@ struct PathSegmentDataStorage #else int nSamples = m_sampleStorage.size(); #endif - for ( int s = 0; s < nSamples; s++) + for (int s = 0; s < nSamples; s++) { SampleData sample = m_sampleStorage[s]; valid = valid && isValid(sample); @@ -532,14 +560,13 @@ struct PathSegmentDataStorage bool validateSegments() const { #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - size_t numSegments = m_seg_idx+1; + size_t numSegments = m_seg_idx + 1; #else size_t numSegments = m_segmentStorage.size(); #endif - bool valid = true; - for ( int s = 0; s < numSegments; s++) + for (int s = 0; s < numSegments; s++) { PathSegmentData psd = m_segmentStorage[s]; valid = valid && isValid(psd); @@ -558,18 +585,18 @@ struct PathSegmentDataStorage std::string toString() const { #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - size_t numSegments = m_seg_idx+1; + size_t numSegments = m_seg_idx + 1; #else size_t numSegments = m_segmentStorage.size(); #endif std::stringstream ss; ss << "PathSegmentDataStorage:" << std::endl; - ss << "segment storage: size = "<< numSegments << std::endl; - for ( int s = 0; s < numSegments; s++) + ss << "segment storage: size = " << numSegments << std::endl; + for (int s = 0; s < numSegments; s++) { PathSegmentData psd = m_segmentStorage[s]; - ss << "seg[" << s << "]: " << openpgl::toString(psd) ; - ss << "\t valid = " << isValid(psd); + ss << "seg[" << s << "]: " << openpgl::toString(psd); + ss << "\t valid = " << isValid(psd); ss << std::endl; } #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) @@ -578,7 +605,7 @@ struct PathSegmentDataStorage int nSamples = m_sampleStorage.size(); #endif - for ( int s = 0; s < nSamples; s++) + for (int s = 0; s < nSamples; s++) { SampleData sample = m_sampleStorage[s]; ss << "sample[" << s << "]: " << openpgl::toString(sample); @@ -588,18 +615,19 @@ struct PathSegmentDataStorage return ss.str(); } - void propagateSamples(SampleDataStorage* sampleDataStorage, const bool guideDirectLight = false, const bool useNEEMiWeights = false, const bool rrAffectsDirectContribution = true) + void propagateSamples(SampleDataStorage *sampleDataStorage, const bool guideDirectLight = false, const bool useNEEMiWeights = false, + const bool rrAffectsDirectContribution = true) { prepareSamples(useNEEMiWeights, guideDirectLight, rrAffectsDirectContribution); #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - sampleDataStorage->addSamples(m_sampleStorage, m_sample_idx+1); + sampleDataStorage->addSamples(m_sampleStorage, m_sample_idx + 1); #else sampleDataStorage->addSamples(m_sampleStorage.data(), m_sampleData.size()); #endif - if(m_track_zero_value_samples) + if (m_track_zero_value_samples) { #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) - sampleDataStorage->addZeroValueSamples(m_zeroValueSampleStorage, m_zero_value_sample_idx+1); + sampleDataStorage->addZeroValueSamples(m_zeroValueSampleStorage, m_zero_value_sample_idx + 1); #else sampleDataStorage->addZeroValueSamples(m_zeroValueSampleStorage.data(), m_zeroValueSampleStorage.size()); #endif @@ -607,7 +635,7 @@ struct PathSegmentDataStorage clear(); } - const ZeroValueSampleData* getZeroValueSamples()const + const ZeroValueSampleData *getZeroValueSamples() const { #if defined(OPENPGL_PATHSEGMENT_STORAGE_USE_ARRAY) return m_zeroValueSampleStorage; @@ -624,6 +652,5 @@ struct PathSegmentDataStorage return m_zeroValueSampleStorage.size(); #endif } - }; -} \ No newline at end of file +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/data/Range.h b/openpgl/data/Range.h index 9f90aba..aadf9d7 100644 --- a/openpgl/data/Range.h +++ b/openpgl/data/Range.h @@ -7,77 +7,80 @@ namespace openpgl { - struct Range - { - size_t m_begin {0}; - size_t m_end {0}; +struct Range +{ + size_t m_begin{0}; + size_t m_end{0}; #ifdef OPENPGL_RADIANCE_CACHES - size_t m_is_begin {0}; - size_t m_is_end {0}; + size_t m_is_begin{0}; + size_t m_is_end{0}; #endif - Range() = default; - Range(size_t begin, size_t end) : m_begin(begin), m_end(end) {} + Range() = default; + Range(size_t begin, size_t end) : m_begin(begin), m_end(end) {} - inline size_t size() const - { - OPENPGL_ASSERT(int(m_end) - int(m_begin) >= 0); - return m_end - m_begin; - } + inline size_t size() const + { + OPENPGL_ASSERT(int(m_end) - int(m_begin) >= 0); + return m_end - m_begin; + } #ifdef OPENPGL_RADIANCE_CACHES - inline size_t sizeZeroValueSamples() const - { - OPENPGL_ASSERT(int(m_is_end) - int(m_is_begin) >= 0); - return m_is_end - m_is_begin; - } + inline size_t sizeZeroValueSamples() const + { + OPENPGL_ASSERT(int(m_is_end) - int(m_is_begin) >= 0); + return m_is_end - m_is_begin; + } #endif - inline void reset() - { - m_begin = 0; - m_end = 0; + inline void reset() + { + m_begin = 0; + m_end = 0; #ifdef OPENPGL_RADIANCE_CACHES - m_is_begin = 0; - m_is_end = 0; + m_is_begin = 0; + m_is_end = 0; #endif - } + } - void serialize(std::ostream &os) const { - os.write(reinterpret_cast(&m_begin), sizeof(m_begin)); - os.write(reinterpret_cast(&m_end), sizeof(m_end)); + void serialize(std::ostream &os) const + { + os.write(reinterpret_cast(&m_begin), sizeof(m_begin)); + os.write(reinterpret_cast(&m_end), sizeof(m_end)); #ifdef OPENPGL_RADIANCE_CACHES - os.write(reinterpret_cast(&m_is_begin), sizeof(m_is_begin)); - os.write(reinterpret_cast(&m_is_end), sizeof(m_is_end)); + os.write(reinterpret_cast(&m_is_begin), sizeof(m_is_begin)); + os.write(reinterpret_cast(&m_is_end), sizeof(m_is_end)); #endif - } + } - void deserialize(std::istream& is) - { - is.read(reinterpret_cast(&m_begin), sizeof(m_begin)); - is.read(reinterpret_cast(&m_end), sizeof(m_end)); + void deserialize(std::istream &is) + { + is.read(reinterpret_cast(&m_begin), sizeof(m_begin)); + is.read(reinterpret_cast(&m_end), sizeof(m_end)); #ifdef OPENPGL_RADIANCE_CACHES - is.read(reinterpret_cast(&m_is_begin), sizeof(m_is_begin)); - is.read(reinterpret_cast(&m_is_end), sizeof(m_is_end)); + is.read(reinterpret_cast(&m_is_begin), sizeof(m_is_begin)); + is.read(reinterpret_cast(&m_is_end), sizeof(m_is_end)); #endif - } + } - bool operator==(const Range& b) const { - bool equal = true; - if(m_begin != b.m_begin || m_end != b.m_end + bool operator==(const Range &b) const + { + bool equal = true; + if (m_begin != b.m_begin || m_end != b.m_end #ifdef OPENPGL_RADIANCE_CACHES - || m_is_begin != b.m_is_begin || m_is_end != b.m_is_end + || m_is_begin != b.m_is_begin || m_is_end != b.m_is_end #endif - ) - { - equal = false; - } - return equal; + ) + { + equal = false; } + return equal; + } - bool isValid() const { - bool valid = true; - valid = valid && m_end >= m_begin; - return valid; - } - }; -} \ No newline at end of file + bool isValid() const + { + bool valid = true; + valid = valid && m_end >= m_begin; + return valid; + } +}; +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/data/SampleContainerInternal.h b/openpgl/data/SampleContainerInternal.h index 57da83f..80b9d6a 100644 --- a/openpgl/data/SampleContainerInternal.h +++ b/openpgl/data/SampleContainerInternal.h @@ -3,156 +3,221 @@ #pragma once -#include "SampleData.h" - -#include #include +#include + +#include "SampleData.h" namespace openpgl { - template - struct ContainerInternal +template +struct ContainerInternal +{ + struct Iterator { - struct Iterator - { - using iterator_category = std::forward_iterator_tag; - using difference_type = std::ptrdiff_t; - using value_type = Type; - using pointer = Type*; - using reference = Type&; - - Iterator() : m_ptr(nullptr) {} - Iterator(pointer ptr) : m_ptr(ptr) {} - - reference operator*() const { return *m_ptr; } - pointer operator->() { return m_ptr; } - - // Prefix and postfix increment - Iterator& operator++() { m_ptr++; return *this; } - Iterator operator++(int) { Iterator tmp = *this; ++(*this); return tmp; } - - // Prefix and postfix decrement - Iterator &operator--() { --m_ptr; return *this; } - Iterator operator--(int) { Iterator tmp(*this); operator--(); return tmp; } - - friend Iterator operator+(const Iterator lhs, const int idx) { return Iterator(lhs.m_ptr+idx);} - friend Iterator operator+=(const Iterator lhs, const int idx) { return Iterator(lhs.m_ptr+idx);} - friend Iterator operator-(const Iterator lhs, const int idx) { return Iterator(lhs.m_ptr-idx);} - friend Iterator operator-=(const Iterator lhs, const int idx) { return Iterator(lhs.m_ptr-idx);} - - friend bool operator== (const Iterator& a, const Iterator& b) { return a.m_ptr == b.m_ptr; }; - friend bool operator!= (const Iterator& a, const Iterator& b) { return a.m_ptr != b.m_ptr; }; - - Iterator::difference_type operator -(const Iterator &it) const - { - return m_ptr - it.m_ptr; - } - - bool operator <(const Iterator &it) const - { - return m_ptr < it.m_ptr; - } - - bool operator <=(const Iterator &it) const - { - return m_ptr <= it.m_ptr; - } - - bool operator >(const Iterator &it) const - { - return m_ptr > it.m_ptr; - } - - bool operator >=(const Iterator &it) const - { - return m_ptr >= it.m_ptr; - } - - value_type& operator[](size_t idx) { - return m_ptr[idx]; - } - const value_type& operator[](size_t idx) const { - return m_ptr[idx]; - } - private: - - pointer m_ptr; + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = Type; + using pointer = Type *; + using reference = Type &; - }; + Iterator() : m_ptr(nullptr) {} + Iterator(pointer ptr) : m_ptr(ptr) {} - using iterator = Iterator; - using value_type = Type; + reference operator*() const + { + return *m_ptr; + } + pointer operator->() + { + return m_ptr; + } - ContainerInternal() = default; - ~ContainerInternal() + // Prefix and postfix increment + Iterator &operator++() { - delete[] m_data; - m_data = nullptr; - m_size = 0; - m_maxSize = 0; + m_ptr++; + return *this; + } + Iterator operator++(int) + { + Iterator tmp = *this; + ++(*this); + return tmp; } - Iterator begin() { - OPENPGL_ASSERT(m_data); - return Iterator(&m_data[0]); + // Prefix and postfix decrement + Iterator &operator--() + { + --m_ptr; + return *this; } - Iterator end() { - OPENPGL_ASSERT(m_data); - OPENPGL_ASSERT(m_size>0); - return Iterator(&m_data[m_size-1]); + Iterator operator--(int) + { + Iterator tmp(*this); + operator--(); + return tmp; } - const Iterator begin() const { - OPENPGL_ASSERT(m_data); - return Iterator(&m_data[0]); + friend Iterator operator+(const Iterator lhs, const int idx) + { + return Iterator(lhs.m_ptr + idx); + } + friend Iterator operator+=(const Iterator lhs, const int idx) + { + return Iterator(lhs.m_ptr + idx); + } + friend Iterator operator-(const Iterator lhs, const int idx) + { + return Iterator(lhs.m_ptr - idx); + } + friend Iterator operator-=(const Iterator lhs, const int idx) + { + return Iterator(lhs.m_ptr - idx); } - const Iterator end() const { return Iterator(&m_data[m_size-1]); } - inline Type* data() { return m_data; } + friend bool operator==(const Iterator &a, const Iterator &b) + { + return a.m_ptr == b.m_ptr; + }; + friend bool operator!=(const Iterator &a, const Iterator &b) + { + return a.m_ptr != b.m_ptr; + }; - inline const Type* data() const { return m_data; } - - inline void reserve(size_t size) + Iterator::difference_type operator-(const Iterator &it) const { - if (size > m_maxSize) - { - delete[] m_data; - m_data = new Type[size]; - m_maxSize = size; - } + return m_ptr - it.m_ptr; } - inline size_t capacity() const {return m_maxSize;}; + bool operator<(const Iterator &it) const + { + return m_ptr < it.m_ptr; + } - inline size_t size() const {return m_size;}; + bool operator<=(const Iterator &it) const + { + return m_ptr <= it.m_ptr; + } - inline void resize(size_t size) + bool operator>(const Iterator &it) const { - reserve(size); - m_size = size; + return m_ptr > it.m_ptr; } - inline void clear() { m_size = 0; } + bool operator>=(const Iterator &it) const + { + return m_ptr >= it.m_ptr; + } - Type& operator[](size_t idx) { - OPENPGL_ASSERT(m_data); - OPENPGL_ASSERT(m_size > 0); - OPENPGL_ASSERT( idx < m_size); - return m_data[idx]; + value_type &operator[](size_t idx) + { + return m_ptr[idx]; } - const Type& operator[](size_t idx) const { - OPENPGL_ASSERT(m_data); - OPENPGL_ASSERT(m_size > 0); - OPENPGL_ASSERT(idx < m_size); - return m_data[idx]; + const value_type &operator[](size_t idx) const + { + return m_ptr[idx]; } - private: - Type* m_data {nullptr}; - size_t m_size {0}; - size_t m_maxSize {0}; + private: + pointer m_ptr; + }; + using iterator = Iterator; + using value_type = Type; + + ContainerInternal() = default; + ~ContainerInternal() + { + delete[] m_data; + m_data = nullptr; + m_size = 0; + m_maxSize = 0; + } + + Iterator begin() + { + OPENPGL_ASSERT(m_data); + return Iterator(&m_data[0]); + } + Iterator end() + { + OPENPGL_ASSERT(m_data); + OPENPGL_ASSERT(m_size > 0); + return Iterator(&m_data[m_size - 1]); + } + + const Iterator begin() const + { + OPENPGL_ASSERT(m_data); + return Iterator(&m_data[0]); + } + const Iterator end() const + { + return Iterator(&m_data[m_size - 1]); + } + + inline Type *data() + { + return m_data; + } + + inline const Type *data() const + { + return m_data; + } + + inline void reserve(size_t size) + { + if (size > m_maxSize) + { + delete[] m_data; + m_data = new Type[size]; + m_maxSize = size; + } + } + + inline size_t capacity() const + { + return m_maxSize; + }; + + inline size_t size() const + { + return m_size; }; -} \ No newline at end of file + inline void resize(size_t size) + { + reserve(size); + m_size = size; + } + + inline void clear() + { + m_size = 0; + } + + Type &operator[](size_t idx) + { + OPENPGL_ASSERT(m_data); + OPENPGL_ASSERT(m_size > 0); + OPENPGL_ASSERT(idx < m_size); + return m_data[idx]; + } + const Type &operator[](size_t idx) const + { + OPENPGL_ASSERT(m_data); + OPENPGL_ASSERT(m_size > 0); + OPENPGL_ASSERT(idx < m_size); + return m_data[idx]; + } + + private: + Type *m_data{nullptr}; + size_t m_size{0}; + size_t m_maxSize{0}; +}; + +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/data/SampleData.h b/openpgl/data/SampleData.h index c35c68e..aee3a04 100644 --- a/openpgl/data/SampleData.h +++ b/openpgl/data/SampleData.h @@ -8,203 +8,205 @@ #include "../include/openpgl/compression.h" #endif -#include "../include/openpgl/data.h" - -#include #include +#include #include +#include "../include/openpgl/data.h" + namespace openpgl { - typedef PGLZeroValueSampleData ZeroValueSampleData; - typedef PGLSampleData SampleData; - enum SampleData_Flags - { - EInsideVolume = 1<<0, // point does not represent any real scene intersection point - EDirectLight = 1<<1 // if the samples represents direct light from a light source - }; +typedef PGLZeroValueSampleData ZeroValueSampleData; +typedef PGLSampleData SampleData; +enum SampleData_Flags +{ + EInsideVolume = 1 << 0, // point does not represent any real scene intersection point + EDirectLight = 1 << 1 // if the samples represents direct light from a light source +}; - inline bool isValid(const SampleData& dsd) - { - bool valid = true; - valid = valid && embree::isvalid(dsd.position.x); - valid = valid && embree::isvalid(dsd.position.y); - valid = valid && embree::isvalid(dsd.position.z); - OPENPGL_ASSERT(valid); - pgl_vec3f d = dsd.direction; - valid = valid && embree::isvalid(d.x); - valid = valid && embree::isvalid(d.y); - valid = valid && embree::isvalid(d.z); - OPENPGL_ASSERT(valid); - valid = valid && embree::isvalid(dsd.weight); - valid = valid && dsd.weight >=0.f; - OPENPGL_ASSERT(valid); - valid = valid && embree::isvalid(dsd.pdf); - valid = valid && dsd.pdf >0.f; - OPENPGL_ASSERT(valid); - valid = valid && embree::isvalid(dsd.distance); - valid = valid && dsd.distance >0.f; - OPENPGL_ASSERT(valid); +inline bool isValid(const SampleData &dsd) +{ + bool valid = true; + valid = valid && embree::isvalid(dsd.position.x); + valid = valid && embree::isvalid(dsd.position.y); + valid = valid && embree::isvalid(dsd.position.z); + OPENPGL_ASSERT(valid); + pgl_vec3f d = dsd.direction; + valid = valid && embree::isvalid(d.x); + valid = valid && embree::isvalid(d.y); + valid = valid && embree::isvalid(d.z); + OPENPGL_ASSERT(valid); + valid = valid && embree::isvalid(dsd.weight); + valid = valid && dsd.weight >= 0.f; + OPENPGL_ASSERT(valid); + valid = valid && embree::isvalid(dsd.pdf); + valid = valid && dsd.pdf > 0.f; + OPENPGL_ASSERT(valid); + valid = valid && embree::isvalid(dsd.distance); + valid = valid && dsd.distance > 0.f; + OPENPGL_ASSERT(valid); #ifdef OPENPGL_RADIANCE_CACHES - pgl_vec3f radianceIn = dsd.radianceIn; - valid = valid && embree::isvalid(radianceIn.x); - valid = valid && radianceIn.x >= 0.f; - valid = valid && embree::isvalid(radianceIn.y); - valid = valid && radianceIn.y >= 0.f; - valid = valid && embree::isvalid(radianceIn.z); - valid = valid && radianceIn.z >= 0.f; - OPENPGL_ASSERT(valid); - valid = valid && embree::isvalid(dsd.radianceInMISWeight); - valid = valid && dsd.radianceInMISWeight >0.f; - OPENPGL_ASSERT(valid); - d = dsd.directionOut; - valid = valid && embree::isvalid(d.x); - valid = valid && embree::isvalid(d.y); - valid = valid && embree::isvalid(d.z); - OPENPGL_ASSERT(valid); - pgl_vec3f radianceOut = dsd.radianceOut; - valid = valid && embree::isvalid(radianceOut.x); - valid = valid && radianceOut.x >= 0.f; - valid = valid && embree::isvalid(radianceOut.y); - valid = valid && radianceOut.y >= 0.f; - valid = valid && embree::isvalid(radianceOut.z); - valid = valid && radianceOut.z >= 0.f; - OPENPGL_ASSERT(valid); + pgl_vec3f radianceIn = dsd.radianceIn; + valid = valid && embree::isvalid(radianceIn.x); + valid = valid && radianceIn.x >= 0.f; + valid = valid && embree::isvalid(radianceIn.y); + valid = valid && radianceIn.y >= 0.f; + valid = valid && embree::isvalid(radianceIn.z); + valid = valid && radianceIn.z >= 0.f; + OPENPGL_ASSERT(valid); + valid = valid && embree::isvalid(dsd.radianceInMISWeight); + valid = valid && dsd.radianceInMISWeight > 0.f; + OPENPGL_ASSERT(valid); + d = dsd.directionOut; + valid = valid && embree::isvalid(d.x); + valid = valid && embree::isvalid(d.y); + valid = valid && embree::isvalid(d.z); + OPENPGL_ASSERT(valid); + pgl_vec3f radianceOut = dsd.radianceOut; + valid = valid && embree::isvalid(radianceOut.x); + valid = valid && radianceOut.x >= 0.f; + valid = valid && embree::isvalid(radianceOut.y); + valid = valid && radianceOut.y >= 0.f; + valid = valid && embree::isvalid(radianceOut.z); + valid = valid && radianceOut.z >= 0.f; + OPENPGL_ASSERT(valid); #endif - return valid; - } + return valid; +} - inline bool isInsideVolume(const SampleData& sd) - { - return (sd.flags & EInsideVolume); - } +inline bool isInsideVolume(const SampleData &sd) +{ + return (sd.flags & EInsideVolume); +} - inline bool isDirectLight(const SampleData& sd) - { - return (sd.flags & EDirectLight); - } +inline bool isDirectLight(const SampleData &sd) +{ + return (sd.flags & EDirectLight); +} - inline std::string toString(const SampleData& sd) - { - std::stringstream ss; - ss << "SampleData: "; - ss << "position = " << sd.position.x << "\t " << sd.position.y << "\t " << sd.position.z << "\t "; - pgl_vec3f direction = sd.direction; - ss << "\t direction = " << direction.x << "\t " << direction.y << "\t " << direction.z << "\t "; - ss << "\t weight = " << sd.weight << "\t "; - ss << "\t pdf = " << sd.pdf << "\t "; - ss << "\t distance = " << sd.distance << "\t "; - ss << "\t flags = " << sd.flags; +inline std::string toString(const SampleData &sd) +{ + std::stringstream ss; + ss << "SampleData: "; + ss << "position = " << sd.position.x << "\t " << sd.position.y << "\t " << sd.position.z << "\t "; + pgl_vec3f direction = sd.direction; + ss << "\t direction = " << direction.x << "\t " << direction.y << "\t " << direction.z << "\t "; + ss << "\t weight = " << sd.weight << "\t "; + ss << "\t pdf = " << sd.pdf << "\t "; + ss << "\t distance = " << sd.distance << "\t "; + ss << "\t flags = " << sd.flags; #ifdef OPENPGL_RADIANCE_CACHES - pgl_vec3f radianceIn = sd.radianceIn; - ss << "\t radianceIn = " << radianceIn.x << "\t " << radianceIn.y << "\t " << radianceIn.z << "\t "; + pgl_vec3f radianceIn = sd.radianceIn; + ss << "\t radianceIn = " << radianceIn.x << "\t " << radianceIn.y << "\t " << radianceIn.z << "\t "; - ss << "\t radianceInMISWeight = " << sd.radianceInMISWeight; + ss << "\t radianceInMISWeight = " << sd.radianceInMISWeight; - pgl_vec3f radianceOut = sd.radianceOut; - ss << "\t radianceOut = " << radianceOut.x << "\t " << radianceOut.y << "\t " << radianceOut.z << "\t "; + pgl_vec3f radianceOut = sd.radianceOut; + ss << "\t radianceOut = " << radianceOut.x << "\t " << radianceOut.y << "\t " << radianceOut.z << "\t "; - pgl_vec3f directionOut = sd.directionOut; - ss << "\t directionOut = " << directionOut.x << "\t " << directionOut.y << "\t " << directionOut.z << "\t "; + pgl_vec3f directionOut = sd.directionOut; + ss << "\t directionOut = " << directionOut.x << "\t " << directionOut.y << "\t " << directionOut.z << "\t "; #endif - ss << std::endl; - - return ss.str(); - } + ss << std::endl; - inline bool SampleDataEqual(const PGLSampleData &compA, const PGLSampleData &compB) - { - if(compA.position.x != compB.position.x || compA.position.y != compB.position.y || - compA.position.z != compB.position.z || + return ss.str(); +} + +inline bool SampleDataEqual(const PGLSampleData &compA, const PGLSampleData &compB) +{ + if (compA.position.x != compB.position.x || compA.position.y != compB.position.y || compA.position.z != compB.position.z || #ifndef PGL_USE_DIRECTION_COMPRESSION - compA.direction.x != compB.direction.x || compA.direction.y != compB.direction.y || compA.direction.z != compB.direction.z || + compA.direction.x != compB.direction.x || compA.direction.y != compB.direction.y || compA.direction.z != compB.direction.z || #else - compA.direction != compB.direction || + compA.direction != compB.direction || #endif - compA.weight != compB.weight || compA.pdf != compB.pdf || - compA.distance != compB.distance || compA.flags != compB.flags) - { - return false; - } - return true; + compA.weight != compB.weight || compA.pdf != compB.pdf || compA.distance != compB.distance || compA.flags != compB.flags) + { + return false; } + return true; +} - inline bool SampleDataLess(const PGLSampleData &compA, const PGLSampleData &compB ) - { - return compA.weight < compB.weight || - ( compA.weight == compB.weight && ( compA.pdf < compB.pdf || - ( compA.pdf == compB.pdf && ( compA.distance < compB.distance || - ( compA.distance == compB.distance && ( compA.position.x < compB.position.x || - (compA.position.x == compB.position.x && ( compA.position.y < compB.position.y || - (compA.position.y == compB.position.y && ( compA.position.z < compB.position.z || - (compA.position.z == compB.position.z && -#ifndef PGL_USE_DIRECTION_COMPRESSION - ( compA.direction.x < compB.direction.x || (compA.direction.x == compB.direction.x && ( compA.direction.y < compB.direction.y || - (compA.direction.y == compB.direction.y && ( compA.direction.z < compB.direction.z ))))) +inline bool SampleDataLess(const PGLSampleData &compA, const PGLSampleData &compB) +{ + return compA.weight < compB.weight || + (compA.weight == compB.weight && + (compA.pdf < compB.pdf || + (compA.pdf == compB.pdf && (compA.distance < compB.distance || + (compA.distance == compB.distance && + (compA.position.x < compB.position.x || + (compA.position.x == compB.position.x && + (compA.position.y < compB.position.y || + (compA.position.y == compB.position.y && + (compA.position.z < compB.position.z || + (compA.position.z == compB.position.z && +#ifndef PGL_USE_DIRECTION_COMPRESSION + (compA.direction.x < compB.direction.x || + (compA.direction.x == compB.direction.x && + (compA.direction.y < compB.direction.y || (compA.direction.y == compB.direction.y && (compA.direction.z < compB.direction.z))))) #else - compA.direction.compressed_direction < compB.direction.compressed_direction + compA.direction.compressed_direction < compB.direction.compressed_direction #endif - ))))))))))); - } + ))))))))))); +} - inline bool ZeroValueSampleDataEqual(const PGLZeroValueSampleData &compA, const PGLZeroValueSampleData &compB) - { - if( compA.position.x != compB.position.x || - compA.position.y != compB.position.y || - compA.position.z != compB.position.z || +inline bool ZeroValueSampleDataEqual(const PGLZeroValueSampleData &compA, const PGLZeroValueSampleData &compB) +{ + if (compA.position.x != compB.position.x || compA.position.y != compB.position.y || compA.position.z != compB.position.z || #ifndef PGL_USE_DIRECTION_COMPRESSION - compA.direction.x != compB.direction.x || - compA.direction.y != compB.direction.y || - compA.direction.z != compB.direction.z + compA.direction.x != compB.direction.x || compA.direction.y != compB.direction.y || compA.direction.z != compB.direction.z #else - compA.direction != compB.direction + compA.direction != compB.direction #endif - ) - { - return false; - } - return true; + ) + { + return false; } + return true; +} - inline bool ZeroValueSampleDataLess(const PGLZeroValueSampleData &compA, const PGLZeroValueSampleData &compB ) - { - return compA.position.x < compB.position.x || (compA.position.x == compB.position.x - && ( compA.position.y < compB.position.y || (compA.position.y == compB.position.y - && ( compA.position.z < compB.position.z || (compA.position.z == compB.position.z +inline bool ZeroValueSampleDataLess(const PGLZeroValueSampleData &compA, const PGLZeroValueSampleData &compB) +{ + return compA.position.x < compB.position.x || + (compA.position.x == compB.position.x && + (compA.position.y < compB.position.y || + (compA.position.y == compB.position.y && + (compA.position.z < compB.position.z || + (compA.position.z == compB.position.z #ifndef PGL_USE_DIRECTION_COMPRESSION - && ( compA.direction.x < compB.direction.x || (compA.direction.x == compB.direction.x - && ( compA.direction.y < compB.direction.y || (compA.direction.y == compB.direction.y - && ( compA.direction.z < compB.direction.z || (compA.direction.z == compB.direction.z - )))))) + && (compA.direction.x < compB.direction.x || + (compA.direction.x == compB.direction.x && + (compA.direction.y < compB.direction.y || + (compA.direction.y == compB.direction.y && (compA.direction.z < compB.direction.z || (compA.direction.z == compB.direction.z)))))) #else - && compA.direction.compressed_direction < compB.direction.compressed_direction -#endif - ))))); - } - - inline SampleData *LoadSampleData(const std::string fileName, size_t &numData){ - - std::ifstream file; - file.open(fileName, std::ios::binary); - file.read((char*)&numData, sizeof(size_t)); + && compA.direction.compressed_direction < compB.direction.compressed_direction +#endif + ))))); +} - SampleData *data = new SampleData[numData]; - file.read((char*)data, numData*sizeof(SampleData)); - file.close(); +inline SampleData *LoadSampleData(const std::string fileName, size_t &numData) +{ + std::ifstream file; + file.open(fileName, std::ios::binary); + file.read((char *)&numData, sizeof(size_t)); - return data; - } + SampleData *data = new SampleData[numData]; + file.read((char *)data, numData * sizeof(SampleData)); + file.close(); - inline void StoreSampleData(const std::string fileName, const SampleData *data, const size_t &numData){ - std::ofstream file; - file.open(fileName, std::ios::binary); + return data; +} - file.write((char*)&numData, sizeof(size_t)); - file.write((char*)&data, numData * sizeof(SampleData)); - file.close(); - } +inline void StoreSampleData(const std::string fileName, const SampleData *data, const size_t &numData) +{ + std::ofstream file; + file.open(fileName, std::ios::binary); + file.write((char *)&numData, sizeof(size_t)); + file.write((char *)&data, numData * sizeof(SampleData)); + file.close(); +} -} \ No newline at end of file +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/data/SampleDataStorage.h b/openpgl/data/SampleDataStorage.h index b9a4487..6abb684 100644 --- a/openpgl/data/SampleDataStorage.h +++ b/openpgl/data/SampleDataStorage.h @@ -9,11 +9,11 @@ #include "../include/openpgl/compression.h" #endif -#include "SampleData.h" - #include #include +#include "SampleData.h" + #define SAMPLE_DATA_STORAGE_FILE_HEADER_STRING "OPENPGL_" OPENPGL_VERSION_STRING "_SAMPLE_STORAGE" namespace openpgl @@ -23,31 +23,34 @@ struct SampleDataStorage { typedef tbb::concurrent_vector SampleDataContainer; typedef tbb::concurrent_vector ZeroValueSampleDataContainer; - struct SampleContainer{ + struct SampleContainer + { SampleDataContainer samples; ZeroValueSampleDataContainer zeroValueSamples; }; - + SampleContainer m_surfaceContainer; SampleContainer m_volumeContainer; - static SampleDataStorage* newSampleDataStorage() + static SampleDataStorage *newSampleDataStorage() { return new openpgl::SampleDataStorage(); } - static SampleDataStorage* newSampleDataStorageFromFile(const std::string sampleDataStorageFileName) + static SampleDataStorage *newSampleDataStorageFromFile(const std::string sampleDataStorageFileName) { std::filebuf fb; - fb.open (sampleDataStorageFileName, std::ios::in | std::ios::binary); - if (!fb.is_open()) throw std::runtime_error("error: couldn't open file"); + fb.open(sampleDataStorageFileName, std::ios::in | std::ios::binary); + if (!fb.is_open()) + throw std::runtime_error("error: couldn't open file"); std::istream is(&fb); auto size = strlen(SAMPLE_DATA_STORAGE_FILE_HEADER_STRING) + 1; OPENPGL_ASSERT(size <= 256); char buf[256]; is.read(&buf[0], size); - if (!is) throw std::runtime_error("error: invalid file header"); + if (!is) + throw std::runtime_error("error: invalid file header"); #ifdef OPENPGL_STRICT_IO_VERSION_CHECKING for (auto i = 0; i < size; i++) { @@ -55,7 +58,7 @@ struct SampleDataStorage throw std::runtime_error("error: invalid file header"); } #endif - openpgl::SampleDataStorage* gSampleStorage = new openpgl::SampleDataStorage(); + openpgl::SampleDataStorage *gSampleStorage = new openpgl::SampleDataStorage(); gSampleStorage->deserialize(is); fb.close(); @@ -63,11 +66,12 @@ struct SampleDataStorage return gSampleStorage; } - static void storeSampleDataStorageToFile(SampleDataStorage* gSampleDataStorage, const std::string sampleDataStorageFileName) + static void storeSampleDataStorageToFile(SampleDataStorage *gSampleDataStorage, const std::string sampleDataStorageFileName) { std::filebuf fb; - fb.open (sampleDataStorageFileName, std::ios::out | std::ios::binary); - if (!fb.is_open()) throw std::runtime_error("error: couldn't open file!"); + fb.open(sampleDataStorageFileName, std::ios::out | std::ios::binary); + if (!fb.is_open()) + throw std::runtime_error("error: couldn't open file!"); std::ostream os(&fb); os.write(SAMPLE_DATA_STORAGE_FILE_HEADER_STRING, strlen(SAMPLE_DATA_STORAGE_FILE_HEADER_STRING) + 1); @@ -78,9 +82,9 @@ struct SampleDataStorage fb.close(); } - inline void addSample(const SampleData& sample) + inline void addSample(const SampleData &sample) { - if(isInsideVolume(sample)) + if (isInsideVolume(sample)) { m_volumeContainer.samples.push_back(sample); } @@ -90,17 +94,17 @@ struct SampleDataStorage } } - inline void addSamples(const SampleData* samples, int nSamples) + inline void addSamples(const SampleData *samples, int nSamples) { - for (int i = 0; i= 0); OPENPGL_ASSERT(idx < m_surfaceContainer.samples.size()); - + SampleData sd; - if(idx < m_surfaceContainer.samples.size()) + if (idx < m_surfaceContainer.samples.size()) { sd = m_surfaceContainer.samples[idx]; } @@ -168,7 +171,7 @@ struct SampleDataStorage OPENPGL_ASSERT(idx < m_volumeContainer.samples.size()); SampleData sd; - if(idx < m_volumeContainer.samples.size()) + if (idx < m_volumeContainer.samples.size()) { sd = m_volumeContainer.samples[idx]; } @@ -199,9 +202,9 @@ struct SampleDataStorage { OPENPGL_ASSERT(idx >= 0); OPENPGL_ASSERT(idx < m_surfaceContainer.zeroValueSamples.size()); - + ZeroValueSampleData isd; - if(idx < m_surfaceContainer.zeroValueSamples.size()) + if (idx < m_surfaceContainer.zeroValueSamples.size()) { isd = m_surfaceContainer.zeroValueSamples[idx]; } @@ -234,7 +237,7 @@ struct SampleDataStorage OPENPGL_ASSERT(idx < m_volumeContainer.zeroValueSamples.size()); ZeroValueSampleData isd; - if(idx < m_volumeContainer.zeroValueSamples.size()) + if (idx < m_volumeContainer.zeroValueSamples.size()) { isd = m_volumeContainer.zeroValueSamples[idx]; } @@ -267,98 +270,101 @@ struct SampleDataStorage objFile.close(); } - - void serialize(std::ostream& stream) const + void serialize(std::ostream &stream) const { size_t num_surface_samples = m_surfaceContainer.samples.size(); - stream.write(reinterpret_cast(&num_surface_samples), sizeof(size_t)); - for ( size_t n = 0; n < num_surface_samples; n++) + stream.write(reinterpret_cast(&num_surface_samples), sizeof(size_t)); + for (size_t n = 0; n < num_surface_samples; n++) { SampleData dsd = m_surfaceContainer.samples[n]; - stream.write(reinterpret_cast(&dsd), sizeof(SampleData)); + stream.write(reinterpret_cast(&dsd), sizeof(SampleData)); } size_t num_volume_samples = m_volumeContainer.samples.size(); - stream.write(reinterpret_cast(&num_volume_samples), sizeof(size_t)); - for ( size_t n = 0; n < num_volume_samples; n++) + stream.write(reinterpret_cast(&num_volume_samples), sizeof(size_t)); + for (size_t n = 0; n < num_volume_samples; n++) { SampleData dsd = m_volumeContainer.samples[n]; - stream.write(reinterpret_cast(&dsd), sizeof(SampleData)); + stream.write(reinterpret_cast(&dsd), sizeof(SampleData)); } size_t num_zero_value_surface_samples = m_surfaceContainer.zeroValueSamples.size(); - stream.write(reinterpret_cast(&num_zero_value_surface_samples), sizeof(size_t)); - for ( size_t n = 0; n < num_zero_value_surface_samples; n++) + stream.write(reinterpret_cast(&num_zero_value_surface_samples), sizeof(size_t)); + for (size_t n = 0; n < num_zero_value_surface_samples; n++) { ZeroValueSampleData isd = m_surfaceContainer.zeroValueSamples[n]; - stream.write(reinterpret_cast(&isd), sizeof(ZeroValueSampleData)); + stream.write(reinterpret_cast(&isd), sizeof(ZeroValueSampleData)); } size_t num_zero_value_volume_samples = m_volumeContainer.zeroValueSamples.size(); - stream.write(reinterpret_cast(&num_zero_value_volume_samples), sizeof(size_t)); - for ( size_t n = 0; n < num_zero_value_volume_samples; n++) + stream.write(reinterpret_cast(&num_zero_value_volume_samples), sizeof(size_t)); + for (size_t n = 0; n < num_zero_value_volume_samples; n++) { ZeroValueSampleData isd = m_volumeContainer.zeroValueSamples[n]; - stream.write(reinterpret_cast(&isd), sizeof(ZeroValueSampleData)); + stream.write(reinterpret_cast(&isd), sizeof(ZeroValueSampleData)); } } - void deserialize(std::istream& stream) + void deserialize(std::istream &stream) { size_t num_surface_samples; - stream.read(reinterpret_cast(&num_surface_samples), sizeof(size_t)); + stream.read(reinterpret_cast(&num_surface_samples), sizeof(size_t)); m_surfaceContainer.samples.reserve(num_surface_samples); - for ( size_t n = 0; n < num_surface_samples; n++) + for (size_t n = 0; n < num_surface_samples; n++) { SampleData dsd; - stream.read(reinterpret_cast(&dsd), sizeof(SampleData)); + stream.read(reinterpret_cast(&dsd), sizeof(SampleData)); m_surfaceContainer.samples.push_back(dsd); } size_t num_volume_samples; - stream.read(reinterpret_cast(&num_volume_samples), sizeof(size_t)); + stream.read(reinterpret_cast(&num_volume_samples), sizeof(size_t)); m_volumeContainer.samples.reserve(num_volume_samples); - for ( size_t n = 0; n < num_volume_samples; n++) + for (size_t n = 0; n < num_volume_samples; n++) { SampleData dsd; - stream.read(reinterpret_cast(&dsd), sizeof(SampleData)); + stream.read(reinterpret_cast(&dsd), sizeof(SampleData)); m_volumeContainer.samples.push_back(dsd); } size_t num_zero_value_surface_samples; - stream.read(reinterpret_cast(&num_zero_value_surface_samples), sizeof(size_t)); + stream.read(reinterpret_cast(&num_zero_value_surface_samples), sizeof(size_t)); m_surfaceContainer.zeroValueSamples.reserve(num_zero_value_surface_samples); - for ( size_t n = 0; n < num_zero_value_surface_samples; n++) + for (size_t n = 0; n < num_zero_value_surface_samples; n++) { ZeroValueSampleData isd; - stream.read(reinterpret_cast(&isd), sizeof(ZeroValueSampleData)); + stream.read(reinterpret_cast(&isd), sizeof(ZeroValueSampleData)); m_surfaceContainer.zeroValueSamples.push_back(isd); } size_t num_zero_value_volume_samples; - stream.read(reinterpret_cast(&num_zero_value_volume_samples), sizeof(size_t)); + stream.read(reinterpret_cast(&num_zero_value_volume_samples), sizeof(size_t)); m_volumeContainer.zeroValueSamples.reserve(num_zero_value_volume_samples); - for ( size_t n = 0; n < num_zero_value_volume_samples; n++) + for (size_t n = 0; n < num_zero_value_volume_samples; n++) { ZeroValueSampleData isd; - stream.read(reinterpret_cast(&isd), sizeof(ZeroValueSampleData)); + stream.read(reinterpret_cast(&isd), sizeof(ZeroValueSampleData)); m_volumeContainer.zeroValueSamples.push_back(isd); } } - bool validate() const { + bool validate() const + { bool valid = true; - for (int i = 0; i < m_surfaceContainer.samples.size(); i++){ + for (int i = 0; i < m_surfaceContainer.samples.size(); i++) + { valid = valid && isValid(m_surfaceContainer.samples[i]); } - for (int i = 0; i < m_volumeContainer.samples.size(); i++){ + for (int i = 0; i < m_volumeContainer.samples.size(); i++) + { valid = valid && isValid(m_volumeContainer.samples[i]); } return valid; } - bool operator==(const SampleDataStorage& b) const { + bool operator==(const SampleDataStorage &b) const + { std::vector surfaceSampleDataA; std::vector volumeSampleDataA; @@ -371,83 +377,99 @@ struct SampleDataStorage std::vector surfaceZeroValueSampleDataB; std::vector volumeZeroValueSampleDataB; - surfaceSampleDataA.resize(m_surfaceContainer.samples.size()); + surfaceSampleDataA.resize(m_surfaceContainer.samples.size()); volumeSampleDataA.resize(m_volumeContainer.samples.size()); - for (int i = 0; i < m_surfaceContainer.samples.size(); i++){ + for (int i = 0; i < m_surfaceContainer.samples.size(); i++) + { surfaceSampleDataA[i] = m_surfaceContainer.samples[i]; } tbb::parallel_sort(surfaceSampleDataA.begin(), surfaceSampleDataA.end(), SampleDataLess); - for (int i = 0; i < m_volumeContainer.samples.size(); i++){ + for (int i = 0; i < m_volumeContainer.samples.size(); i++) + { volumeSampleDataA[i] = m_volumeContainer.samples[i]; } tbb::parallel_sort(volumeSampleDataA.begin(), volumeSampleDataA.end(), SampleDataLess); - surfaceZeroValueSampleDataA.resize(m_surfaceContainer.zeroValueSamples.size()); + surfaceZeroValueSampleDataA.resize(m_surfaceContainer.zeroValueSamples.size()); volumeZeroValueSampleDataA.resize(m_volumeContainer.zeroValueSamples.size()); - for (int i = 0; i < m_surfaceContainer.zeroValueSamples.size(); i++){ + for (int i = 0; i < m_surfaceContainer.zeroValueSamples.size(); i++) + { surfaceZeroValueSampleDataA[i] = m_surfaceContainer.zeroValueSamples[i]; } tbb::parallel_sort(surfaceZeroValueSampleDataA.begin(), surfaceZeroValueSampleDataA.end(), ZeroValueSampleDataLess); - for (int i = 0; i < m_volumeContainer.zeroValueSamples.size(); i++){ + for (int i = 0; i < m_volumeContainer.zeroValueSamples.size(); i++) + { volumeZeroValueSampleDataA[i] = m_volumeContainer.zeroValueSamples[i]; } tbb::parallel_sort(volumeZeroValueSampleDataA.begin(), volumeZeroValueSampleDataA.end(), ZeroValueSampleDataLess); - surfaceSampleDataB.resize(b.m_surfaceContainer.samples.size()); + surfaceSampleDataB.resize(b.m_surfaceContainer.samples.size()); volumeSampleDataB.resize(b.m_volumeContainer.samples.size()); - for (int i = 0; i < b.m_surfaceContainer.samples.size(); i++){ + for (int i = 0; i < b.m_surfaceContainer.samples.size(); i++) + { surfaceSampleDataB[i] = b.m_surfaceContainer.samples[i]; } tbb::parallel_sort(surfaceSampleDataB.begin(), surfaceSampleDataB.end(), SampleDataLess); - for (int i = 0; i < b.m_volumeContainer.samples.size(); i++){ + for (int i = 0; i < b.m_volumeContainer.samples.size(); i++) + { volumeSampleDataB[i] = b.m_volumeContainer.samples[i]; } - tbb::parallel_sort(volumeSampleDataB.begin(), volumeSampleDataB.end(), SampleDataLess); + tbb::parallel_sort(volumeSampleDataB.begin(), volumeSampleDataB.end(), SampleDataLess); - surfaceZeroValueSampleDataB.resize(b.m_surfaceContainer.zeroValueSamples.size()); + surfaceZeroValueSampleDataB.resize(b.m_surfaceContainer.zeroValueSamples.size()); volumeZeroValueSampleDataB.resize(b.m_volumeContainer.zeroValueSamples.size()); - for (int i = 0; i < b.m_surfaceContainer.zeroValueSamples.size(); i++){ + for (int i = 0; i < b.m_surfaceContainer.zeroValueSamples.size(); i++) + { surfaceZeroValueSampleDataB[i] = b.m_surfaceContainer.zeroValueSamples[i]; } tbb::parallel_sort(surfaceZeroValueSampleDataB.begin(), surfaceZeroValueSampleDataB.end(), ZeroValueSampleDataLess); - for (int i = 0; i < b.m_volumeContainer.zeroValueSamples.size(); i++){ + for (int i = 0; i < b.m_volumeContainer.zeroValueSamples.size(); i++) + { volumeZeroValueSampleDataB[i] = b.m_volumeContainer.zeroValueSamples[i]; } tbb::parallel_sort(volumeZeroValueSampleDataB.begin(), volumeZeroValueSampleDataB.end(), ZeroValueSampleDataLess); bool equal = true; int sizeB = surfaceSampleDataB.size(); - for (int i = 0; i < surfaceSampleDataA.size(); i++) { - if( i< sizeB && !SampleDataEqual(surfaceSampleDataA[i], surfaceSampleDataB[i])){ + for (int i = 0; i < surfaceSampleDataA.size(); i++) + { + if (i < sizeB && !SampleDataEqual(surfaceSampleDataA[i], surfaceSampleDataB[i])) + { equal = false; } } sizeB = surfaceZeroValueSampleDataB.size(); - for (int i = 0; i < surfaceZeroValueSampleDataA.size(); i++) { - if( i< sizeB && !ZeroValueSampleDataEqual(surfaceZeroValueSampleDataA[i], surfaceZeroValueSampleDataB[i])){ + for (int i = 0; i < surfaceZeroValueSampleDataA.size(); i++) + { + if (i < sizeB && !ZeroValueSampleDataEqual(surfaceZeroValueSampleDataA[i], surfaceZeroValueSampleDataB[i])) + { equal = false; } } sizeB = volumeSampleDataB.size(); - for (int i = 0; i < volumeSampleDataA.size(); i++) { - if( i< sizeB && !SampleDataEqual(volumeSampleDataA[i], volumeSampleDataB[i])){ + for (int i = 0; i < volumeSampleDataA.size(); i++) + { + if (i < sizeB && !SampleDataEqual(volumeSampleDataA[i], volumeSampleDataB[i])) + { equal = false; } } sizeB = volumeZeroValueSampleDataB.size(); - for (int i = 0; i < volumeZeroValueSampleDataA.size(); i++) { - if( i< sizeB && !ZeroValueSampleDataEqual(volumeZeroValueSampleDataA[i], volumeZeroValueSampleDataB[i])){ + for (int i = 0; i < volumeZeroValueSampleDataA.size(); i++) + { + if (i < sizeB && !ZeroValueSampleDataEqual(volumeZeroValueSampleDataA[i], volumeZeroValueSampleDataB[i])) + { equal = false; } } @@ -455,40 +477,39 @@ struct SampleDataStorage return equal; } - private: - + private: void exportSamplesToObj(std::ofstream &objFile, const SampleDataContainer &sampleContainer, bool pointsOnly = true) { std::vector subSampledData; subSampledData.reserve(sampleContainer.size()); - for (size_t i =0; i < sampleContainer.size(); i++) + for (size_t i = 0; i < sampleContainer.size(); i++) { subSampledData.push_back(sampleContainer[i]); } - for (auto& sample : subSampledData) + for (auto &sample : subSampledData) { - objFile << "v " << sample.position.x << "\t" << sample.position.y << "\t"<< sample.position.z << std::endl; + objFile << "v " << sample.position.x << "\t" << sample.position.y << "\t" << sample.position.z << std::endl; if (!pointsOnly) { pgl_vec3f direction = sample.direction; Vector3 dir(direction.x, direction.y, direction.z); Point3 samplePosition(sample.position.x, sample.position.y, sample.position.z); Point3 pos2 = samplePosition + dir * sample.distance; - objFile << "v " << pos2[0] << "\t" << pos2[1] << "\t"<< pos2[2] << std::endl; - objFile << "v " << sample.position.x << "\t" << sample.position.y << "\t"<< sample.position.z << std::endl; + objFile << "v " << pos2[0] << "\t" << pos2[1] << "\t" << pos2[2] << std::endl; + objFile << "v " << sample.position.x << "\t" << sample.position.y << "\t" << sample.position.z << std::endl; } } - for (auto& sample : subSampledData) + for (auto &sample : subSampledData) { pgl_vec3f direction = sample.direction; Vector3 dir(direction.x, direction.y, direction.z); - objFile << "vn " << dir[0] << "\t" << dir[1] << "\t"<< dir[2] << std::endl; + objFile << "vn " << dir[0] << "\t" << dir[1] << "\t" << dir[2] << std::endl; if (!pointsOnly) { - objFile << "vn " << dir[0] << "\t" << dir[1] << "\t"<< dir[2] << std::endl; - objFile << "vn " << dir[0] << "\t" << dir[1] << "\t"<< dir[2] << std::endl; + objFile << "vn " << dir[0] << "\t" << dir[1] << "\t" << dir[2] << std::endl; + objFile << "vn " << dir[0] << "\t" << dir[1] << "\t" << dir[2] << std::endl; } } @@ -496,10 +517,10 @@ struct SampleDataStorage { for (int i = 0; i < subSampledData.size(); i++) { - objFile << "f " << i*3+1 << "\t" << i*3+2 << "\t"<< i*3+3 << std::endl; + objFile << "f " << i * 3 + 1 << "\t" << i * 3 + 2 << "\t" << i * 3 + 3 << std::endl; } } } }; -} +} // namespace openpgl diff --git a/openpgl/data/SampleStatistics.h b/openpgl/data/SampleStatistics.h index c9ef002..8ac3ecb 100644 --- a/openpgl/data/SampleStatistics.h +++ b/openpgl/data/SampleStatistics.h @@ -9,356 +9,359 @@ namespace openpgl { - struct SampleStatistics - { - Point3 mean{0.0f}; - Vector3 sampleVariance {0.0f}; - float numSamples {0}; - float numZeroValueSamples {0.0f}; - - BBox sampleBounds{openpgl::Vector3(std::numeric_limits::max()), openpgl::Vector3(-std::numeric_limits::max())}; +struct SampleStatistics +{ + Point3 mean{0.0f}; + Vector3 sampleVariance{0.0f}; + float numSamples{0}; + float numZeroValueSamples{0.0f}; - inline void clear() - { - mean = Point3(0.0f); - sampleVariance = Vector3(0.0f); - numSamples = 0.0f; - numZeroValueSamples = 0.0f; - sampleBounds.lower = openpgl::Vector3(std::numeric_limits::max()); - sampleBounds.upper = openpgl::Vector3(-std::numeric_limits::max()); - } + BBox sampleBounds{openpgl::Vector3(std::numeric_limits::max()), openpgl::Vector3(-std::numeric_limits::max())}; - inline void addSample( const Point3 sample) - { - numSamples++; - float incWeight = embree::rcp(float(numSamples)); - OPENPGL_ASSERT(numSamples > 0.0f); - OPENPGL_ASSERT(embree::isvalid(incWeight)); - OPENPGL_ASSERT(incWeight >=0.0f); - - const Point3 oldMean = mean; - mean += (sample - oldMean) * incWeight; - - //mean += sample; - //const Point3 newMean = mean * incWeight; - sampleVariance += ((sample - oldMean) * (sample - mean)); - sampleBounds.extend( sample ); - } + inline void clear() + { + mean = Point3(0.0f); + sampleVariance = Vector3(0.0f); + numSamples = 0.0f; + numZeroValueSamples = 0.0f; + sampleBounds.lower = openpgl::Vector3(std::numeric_limits::max()); + sampleBounds.upper = openpgl::Vector3(-std::numeric_limits::max()); + } + + inline void addSample(const Point3 sample) + { + numSamples++; + float incWeight = embree::rcp(float(numSamples)); + OPENPGL_ASSERT(numSamples > 0.0f); + OPENPGL_ASSERT(embree::isvalid(incWeight)); + OPENPGL_ASSERT(incWeight >= 0.0f); + + const Point3 oldMean = mean; + mean += (sample - oldMean) * incWeight; + + // mean += sample; + // const Point3 newMean = mean * incWeight; + sampleVariance += ((sample - oldMean) * (sample - mean)); + sampleBounds.extend(sample); + } + + inline Point3 getMean() const + { + return mean; // / float(numSamples); + } - inline Point3 getMean() const - { - return mean; // / float(numSamples); - } + inline Vector3 getVariance() const + { + OPENPGL_ASSERT(numSamples > 0.f); + return sampleVariance / float(numSamples); + } - inline Vector3 getVariance() const - { - OPENPGL_ASSERT( numSamples > 0.f); - return sampleVariance / float(numSamples); - } + inline void decay(const float &a) + { + numSamples *= a; + sampleVariance *= a; + numZeroValueSamples *= a; + } - inline void decay( const float &a) - { - numSamples *= a; - sampleVariance *= a; - numZeroValueSamples *= a; - } + inline float getNumSamples() const + { + return numSamples; + } - inline float getNumSamples() const - { - return numSamples; - } + inline void addNumZeroValueSamples(const int numZeroValueSamples) + { + this->numZeroValueSamples += numZeroValueSamples; + } - inline void addNumZeroValueSamples( const int numZeroValueSamples) - { - this->numZeroValueSamples += numZeroValueSamples; - } + inline float getNumZeroValueSamples() const + { + return numZeroValueSamples; + } - inline float getNumZeroValueSamples() const - { - return numZeroValueSamples; - } + void split(const uint8_t &splitDim, const float &splitPos, const float &decay, const bool &splitLower) + { + OPENPGL_ASSERT(decay > 0.0f && decay <= 1.0f); - void split(const uint8_t &splitDim, const float &splitPos, const float &decay, const bool &splitLower) + if (numSamples > 0.f) { - OPENPGL_ASSERT(decay >0.0f && decay <= 1.0f) ; + const float variance = sampleVariance[splitDim] / numSamples; + const float stdDerivation = std::sqrt(variance); - if(numSamples > 0.f) + float const newVariance = variance - variance / 4.0f; + sampleVariance[splitDim] = newVariance * numSamples; + if (splitLower) { - const float variance = sampleVariance[splitDim] / numSamples; - const float stdDerivation = std::sqrt(variance); - - float const newVariance = variance - variance / 4.0f; - sampleVariance[splitDim] = newVariance * numSamples; - if(splitLower) - { - sampleBounds.lower[splitDim] = std::max(splitPos, sampleBounds.lower[splitDim]); - mean[splitDim] = std::min(sampleBounds.upper[splitDim], mean[splitDim] + stdDerivation / 2.0f); - // TODO: there are rare ocasions where this can happen (boarder of the head scene) - // find a way to handle these - //OPENPGL_ASSERT(mean[splitDim] >= sampleBounds.lower[splitDim]); - //mean[splitDim] += stdDerivation / 2.0f; - } - else - { - sampleBounds.upper[splitDim] = std::min(splitPos, sampleBounds.upper[splitDim]); - mean[splitDim] = std::max(sampleBounds.lower[splitDim], mean[splitDim] - stdDerivation / 2.0f); - //OPENPGL_ASSERT(mean[splitDim] <= sampleBounds.upper[splitDim]); - //mean[splitDim] -= stdDerivation / 2.0f; - } - - numSamples *= decay; - numZeroValueSamples *= decay; - sampleVariance *= decay; + sampleBounds.lower[splitDim] = std::max(splitPos, sampleBounds.lower[splitDim]); + mean[splitDim] = std::min(sampleBounds.upper[splitDim], mean[splitDim] + stdDerivation / 2.0f); + // TODO: there are rare ocasions where this can happen (boarder of the head scene) + // find a way to handle these + // OPENPGL_ASSERT(mean[splitDim] >= sampleBounds.lower[splitDim]); + // mean[splitDim] += stdDerivation / 2.0f; + } + else + { + sampleBounds.upper[splitDim] = std::min(splitPos, sampleBounds.upper[splitDim]); + mean[splitDim] = std::max(sampleBounds.lower[splitDim], mean[splitDim] - stdDerivation / 2.0f); + // OPENPGL_ASSERT(mean[splitDim] <= sampleBounds.upper[splitDim]); + // mean[splitDim] -= stdDerivation / 2.0f; } - } - void merge( const SampleStatistics &b) - { - const Point3 meanA = mean; - const Point3 meanB = b.mean; + numSamples *= decay; + numZeroValueSamples *= decay; + sampleVariance *= decay; + } + } - const Vector3 sampleVarianceA = sampleVariance; - const Vector3 sampleVarianceB = b.sampleVariance; + void merge(const SampleStatistics &b) + { + const Point3 meanA = mean; + const Point3 meanB = b.mean; - const float numSamplesA = numSamples; - const float numSamplesB = b.numSamples; + const Vector3 sampleVarianceA = sampleVariance; + const Vector3 sampleVarianceB = b.sampleVariance; - mean = meanA*(float)numSamplesA + meanB*(float)numSamplesB; - numSamples += numSamplesB; - mean /= float(numSamples); + const float numSamplesA = numSamples; + const float numSamplesB = b.numSamples; - sampleVariance = (sampleVarianceA + numSamplesA*meanA*meanA + sampleVarianceB + numSamplesB*meanB*meanB) - numSamples * mean*mean; - sampleBounds.extend(b.sampleBounds); + mean = meanA * (float)numSamplesA + meanB * (float)numSamplesB; + numSamples += numSamplesB; + mean /= float(numSamples); - numZeroValueSamples += b.numZeroValueSamples; - } + sampleVariance = (sampleVarianceA + numSamplesA * meanA * meanA + sampleVarianceB + numSamplesB * meanB * meanB) - numSamples * mean * mean; + sampleBounds.extend(b.sampleBounds); - inline bool isValid() const - { - bool valid = true; - valid = valid && numSamples >=0.0f; - valid = valid && numZeroValueSamples >=0.0f; + numZeroValueSamples += b.numZeroValueSamples; + } - valid = valid && embree::isvalid(mean.x); - valid = valid && embree::isvalid(mean.y); - valid = valid && embree::isvalid(mean.z); + inline bool isValid() const + { + bool valid = true; + valid = valid && numSamples >= 0.0f; + valid = valid && numZeroValueSamples >= 0.0f; - valid = valid && embree::isvalid(sampleVariance.x); - valid = valid && embree::isvalid(sampleVariance.y); - valid = valid && embree::isvalid(sampleVariance.z); + valid = valid && embree::isvalid(mean.x); + valid = valid && embree::isvalid(mean.y); + valid = valid && embree::isvalid(mean.z); - return valid; - } + valid = valid && embree::isvalid(sampleVariance.x); + valid = valid && embree::isvalid(sampleVariance.y); + valid = valid && embree::isvalid(sampleVariance.z); - SampleStatistics operator()(const SampleStatistics &a, const SampleStatistics &b) const{ - SampleStatistics merged = a; - merged.merge(b); - return merged; - } + return valid; + } - std::string toString() const - { - Vector3 variance = getVariance(); - std::stringstream ss; - ss.precision(5); - ss << "SampleStatistics:" << std::endl; - ss << "numSamples: " << numSamples << std::endl; - ss << "numZeroValueSamples: " << numZeroValueSamples << std::endl; - ss << "mean: " << mean[0] << ",\t"<< mean[1] << ",\t"<< mean[2] << std::endl; - ss << "variance: " << variance[0] << ",\t"<< variance[1] << ",\t"<< variance[2] << std::endl; - ss << "sampleBounds: [" << sampleBounds.lower[0] << ",\t"<< sampleBounds.lower[1] << ",\t"<< sampleBounds.lower[2] << "] \t [" << sampleBounds.upper[0] << ",\t"<< sampleBounds.upper[1] << ",\t"<< sampleBounds.upper[2] << "] "<< std::endl; - //ss << "maxComponents: " << maxComponents << std::endl; - //ss << "maxComponents: " << maxComponents << std::endl; - return ss.str(); - } - - void serialize(std::ostream& stream) const - { - stream.write(reinterpret_cast(&mean), sizeof(Point3)); - stream.write(reinterpret_cast(&sampleVariance), sizeof(Vector3)); - stream.write(reinterpret_cast(&numSamples), sizeof(float)); - stream.write(reinterpret_cast(&numZeroValueSamples), sizeof(float)); - stream.write(reinterpret_cast(&sampleBounds), sizeof(BBox)); - } + SampleStatistics operator()(const SampleStatistics &a, const SampleStatistics &b) const + { + SampleStatistics merged = a; + merged.merge(b); + return merged; + } - void deserialize(std::istream& stream) + std::string toString() const + { + Vector3 variance = getVariance(); + std::stringstream ss; + ss.precision(5); + ss << "SampleStatistics:" << std::endl; + ss << "numSamples: " << numSamples << std::endl; + ss << "numZeroValueSamples: " << numZeroValueSamples << std::endl; + ss << "mean: " << mean[0] << ",\t" << mean[1] << ",\t" << mean[2] << std::endl; + ss << "variance: " << variance[0] << ",\t" << variance[1] << ",\t" << variance[2] << std::endl; + ss << "sampleBounds: [" << sampleBounds.lower[0] << ",\t" << sampleBounds.lower[1] << ",\t" << sampleBounds.lower[2] << "] \t [" << sampleBounds.upper[0] << ",\t" + << sampleBounds.upper[1] << ",\t" << sampleBounds.upper[2] << "] " << std::endl; + // ss << "maxComponents: " << maxComponents << std::endl; + // ss << "maxComponents: " << maxComponents << std::endl; + return ss.str(); + } + + void serialize(std::ostream &stream) const + { + stream.write(reinterpret_cast(&mean), sizeof(Point3)); + stream.write(reinterpret_cast(&sampleVariance), sizeof(Vector3)); + stream.write(reinterpret_cast(&numSamples), sizeof(float)); + stream.write(reinterpret_cast(&numZeroValueSamples), sizeof(float)); + stream.write(reinterpret_cast(&sampleBounds), sizeof(BBox)); + } + + void deserialize(std::istream &stream) + { + stream.read(reinterpret_cast(&mean), sizeof(Point3)); + stream.read(reinterpret_cast(&sampleVariance), sizeof(Vector3)); + stream.read(reinterpret_cast(&numSamples), sizeof(float)); + stream.read(reinterpret_cast(&numZeroValueSamples), sizeof(float)); + stream.read(reinterpret_cast(&sampleBounds), sizeof(BBox)); + } + + bool operator==(const SampleStatistics &b) const + { + bool equal = true; + if (mean.x != b.mean.x || mean.y != b.mean.y || mean.z != b.mean.z || sampleVariance.x != b.sampleVariance.x || sampleVariance.y != b.sampleVariance.y || + sampleVariance.z != b.sampleVariance.z || numSamples != b.numSamples || sampleBounds.lower.x != b.sampleBounds.lower.x || + sampleBounds.lower.y != b.sampleBounds.lower.y || sampleBounds.lower.z != b.sampleBounds.lower.z || sampleBounds.upper.x != b.sampleBounds.upper.x || + sampleBounds.upper.y != b.sampleBounds.upper.y || sampleBounds.upper.z != b.sampleBounds.upper.z) { - stream.read(reinterpret_cast(&mean), sizeof(Point3)); - stream.read(reinterpret_cast(&sampleVariance), sizeof(Vector3)); - stream.read(reinterpret_cast(&numSamples), sizeof(float)); - stream.read(reinterpret_cast(&numZeroValueSamples), sizeof(float)); - stream.read(reinterpret_cast(&sampleBounds), sizeof(BBox)); + equal = false; + // std::cout << std::fixed; + // std::cout << std::setprecision(12); + // std::cout << "SampleStatistics: NOT-EQUAL" << std::endl; + // std::cout << "SampleStatisticsLeft: numSamples = " << numSamples << "\t mean = " << mean.x << "\t" << mean.y << "\t" << mean.z << "\t sampleVariance = "<< + // sampleVariance.x << "\t" << sampleVariance.y << "\t" << sampleVariance.z << std::endl; std::cout << "SampleStatisticsRight: numSamples = " << b.numSamples << "\t + // mean = " << b.mean.x << "\t" << b.mean.y << "\t" << b.mean.z << "\t sampleVariance = "<< b.sampleVariance.x << "\t" << b.sampleVariance.y << "\t" << + // b.sampleVariance.z << std::endl; } + return equal; + } +}; - bool operator==(const SampleStatistics& b) const { - bool equal = true; - if(mean.x != b.mean.x || mean.y != b.mean.y || - mean.z != b.mean.z || sampleVariance.x != b.sampleVariance.x || - sampleVariance.y != b.sampleVariance.y || sampleVariance.z != b.sampleVariance.z || - numSamples != b.numSamples || sampleBounds.lower.x != b.sampleBounds.lower.x || - sampleBounds.lower.y != b.sampleBounds.lower.y || sampleBounds.lower.z != b.sampleBounds.lower.z || - sampleBounds.upper.x != b.sampleBounds.upper.x || sampleBounds.upper.y != b.sampleBounds.upper.y || - sampleBounds.upper.z != b.sampleBounds.upper.z) - { - equal = false; - //std::cout << std::fixed; - //std::cout << std::setprecision(12); - //std::cout << "SampleStatistics: NOT-EQUAL" << std::endl; - //std::cout << "SampleStatisticsLeft: numSamples = " << numSamples << "\t mean = " << mean.x << "\t" << mean.y << "\t" << mean.z << "\t sampleVariance = "<< sampleVariance.x << "\t" << sampleVariance.y << "\t" << sampleVariance.z << std::endl; - //std::cout << "SampleStatisticsRight: numSamples = " << b.numSamples << "\t mean = " << b.mean.x << "\t" << b.mean.y << "\t" << b.mean.z << "\t sampleVariance = "<< b.sampleVariance.x << "\t" << b.sampleVariance.y << "\t" << b.sampleVariance.z << std::endl; - } - return equal; - } - - }; - - #define INTEGER_BINS 4096.f - struct IntegerSampleStatistics - { - Point3i mean{0}; - Vector3i variance {0}; - uint32_t numSamples {0}; - BBoxi sampleBounds{openpgl::Vector3i(std::numeric_limits::max()), openpgl::Vector3i(-std::numeric_limits::max())}; - Vector3 sampleBoundsMin {0}; - Vector3 sampleBoundsMax {0}; - Vector3 sampleBoundsExtend {0}; - Vector3 invSampleBoundsExtend {0}; -#ifdef INTERGER_V2 - Vector3 sampleBoundsCenter {0}; - Vector3 sampleBoundsHalfExtend {0}; - Vector3 invSampleBoundsHalfExtend {0}; -#endif - IntegerSampleStatistics(){ - mean = Point3i(0); - variance = Vector3i(0); - numSamples = 0; - sampleBounds = BBoxi(openpgl::Vector3i(std::numeric_limits::max()), openpgl::Vector3i(-std::numeric_limits::max())); - sampleBoundsMin = Vector3(0); - sampleBoundsMax = Vector3(0); - sampleBoundsExtend = Vector3(0); - invSampleBoundsExtend = Vector3(0); +#define INTEGER_BINS 4096.f +struct IntegerSampleStatistics +{ + Point3i mean{0}; + Vector3i variance{0}; + uint32_t numSamples{0}; + BBoxi sampleBounds{openpgl::Vector3i(std::numeric_limits::max()), openpgl::Vector3i(-std::numeric_limits::max())}; + Vector3 sampleBoundsMin{0}; + Vector3 sampleBoundsMax{0}; + Vector3 sampleBoundsExtend{0}; + Vector3 invSampleBoundsExtend{0}; #ifdef INTERGER_V2 - sampleBoundsCenter = Vector3(0); - sampleBoundsHalfExtend = Vector3(0); - invSampleBoundsHalfExtend = Vector3(0); + Vector3 sampleBoundsCenter{0}; + Vector3 sampleBoundsHalfExtend{0}; + Vector3 invSampleBoundsHalfExtend{0}; #endif - } - - IntegerSampleStatistics(const BBox& bounds){ - mean = Point3i(0); - variance = Vector3i(0); - numSamples = 0; - sampleBounds = BBoxi(openpgl::Vector3i(std::numeric_limits::max()), openpgl::Vector3i(-std::numeric_limits::max())); - sampleBoundsMin = bounds.lower; - sampleBoundsMax = bounds.upper; - sampleBoundsExtend = bounds.upper - bounds.lower; - invSampleBoundsExtend = embree::rcp(sampleBoundsExtend); + IntegerSampleStatistics() + { + mean = Point3i(0); + variance = Vector3i(0); + numSamples = 0; + sampleBounds = BBoxi(openpgl::Vector3i(std::numeric_limits::max()), openpgl::Vector3i(-std::numeric_limits::max())); + sampleBoundsMin = Vector3(0); + sampleBoundsMax = Vector3(0); + sampleBoundsExtend = Vector3(0); + invSampleBoundsExtend = Vector3(0); #ifdef INTERGER_V2 - sampleBoundsHalfExtend = sampleBoundsExtend * 0.5f; - invSampleBoundsHalfExtend = embree::rcp(sampleBoundsHalfExtend); - sampleBoundsCenter = sampleBoundsMin + sampleBoundsHalfExtend; + sampleBoundsCenter = Vector3(0); + sampleBoundsHalfExtend = Vector3(0); + invSampleBoundsHalfExtend = Vector3(0); #endif - } + } + IntegerSampleStatistics(const BBox &bounds) + { + mean = Point3i(0); + variance = Vector3i(0); + numSamples = 0; + sampleBounds = BBoxi(openpgl::Vector3i(std::numeric_limits::max()), openpgl::Vector3i(-std::numeric_limits::max())); + sampleBoundsMin = bounds.lower; + sampleBoundsMax = bounds.upper; + sampleBoundsExtend = bounds.upper - bounds.lower; + invSampleBoundsExtend = embree::rcp(sampleBoundsExtend); +#ifdef INTERGER_V2 + sampleBoundsHalfExtend = sampleBoundsExtend * 0.5f; + invSampleBoundsHalfExtend = embree::rcp(sampleBoundsHalfExtend); + sampleBoundsCenter = sampleBoundsMin + sampleBoundsHalfExtend; +#endif + } - void clear() { - mean = Point3i(0); - variance = Vector3i(0); - numSamples = 0; - - sampleBounds = BBoxi(openpgl::Vector3i(std::numeric_limits::max()), openpgl::Vector3i(-std::numeric_limits::max())); - sampleBoundsMin = Vector3(0); - sampleBoundsMax = Vector3(0); - sampleBoundsExtend = Vector3(0); - invSampleBoundsExtend = Vector3(0); + void clear() + { + mean = Point3i(0); + variance = Vector3i(0); + numSamples = 0; + + sampleBounds = BBoxi(openpgl::Vector3i(std::numeric_limits::max()), openpgl::Vector3i(-std::numeric_limits::max())); + sampleBoundsMin = Vector3(0); + sampleBoundsMax = Vector3(0); + sampleBoundsExtend = Vector3(0); + invSampleBoundsExtend = Vector3(0); #ifdef INTERGER_V2 - sampleBoundsCenter = Vector3(0); - sampleBoundsHalfExtend = Vector3(0); - invSampleBoundsHalfExtend = Vector3(0); + sampleBoundsCenter = Vector3(0); + sampleBoundsHalfExtend = Vector3(0); + invSampleBoundsHalfExtend = Vector3(0); #endif - } + } - inline void addSample( const Point3 sample) - { - numSamples++; + inline void addSample(const Point3 sample) + { + numSamples++; #ifdef INTERGER_V2 - Point3 tmpSample = ((sample - sampleBoundsCenter) * invSampleBoundsHalfExtend); //* INTEGER_BINS; + Point3 tmpSample = ((sample - sampleBoundsCenter) * invSampleBoundsHalfExtend); //* INTEGER_BINS; #else - Point3 tmpSample = ((sample - sampleBoundsMin) * invSampleBoundsExtend); //* INTEGER_BINS; + Point3 tmpSample = ((sample - sampleBoundsMin) * invSampleBoundsExtend); //* INTEGER_BINS; #endif - Vector3 tmpVariance = (tmpSample * tmpSample) * INTEGER_BINS; - tmpSample *= INTEGER_BINS; + Vector3 tmpVariance = (tmpSample * tmpSample) * INTEGER_BINS; + tmpSample *= INTEGER_BINS; - Point3i iSample(tmpSample.x, tmpSample.y, tmpSample.z); - mean += iSample; - variance += Vector3i(tmpVariance.x, tmpVariance.y, tmpVariance.z); + Point3i iSample(tmpSample.x, tmpSample.y, tmpSample.z); + mean += iSample; + variance += Vector3i(tmpVariance.x, tmpVariance.y, tmpVariance.z); - sampleBounds.extend(iSample); - } + sampleBounds.extend(iSample); + } - void merge( const IntegerSampleStatistics &b) - { - mean += b.mean; - variance += b.variance; - numSamples += b.numSamples; - sampleBounds.extend(b.sampleBounds); - } + void merge(const IntegerSampleStatistics &b) + { + mean += b.mean; + variance += b.variance; + numSamples += b.numSamples; + sampleBounds.extend(b.sampleBounds); + } - static IntegerSampleStatistics merge(const IntegerSampleStatistics &a, const IntegerSampleStatistics &b) + static IntegerSampleStatistics merge(const IntegerSampleStatistics &a, const IntegerSampleStatistics &b) + { + IntegerSampleStatistics stats = a; + stats.mean += b.mean; + stats.variance += b.variance; + stats.numSamples += b.numSamples; + stats.sampleBounds.extend(b.sampleBounds); + return stats; + } + + SampleStatistics getSampleStatistics() const + { + SampleStatistics sampleStats; + if (numSamples > 0) { - IntegerSampleStatistics stats = a; - stats.mean += b.mean; - stats.variance += b.variance; - stats.numSamples += b.numSamples; - stats.sampleBounds.extend(b.sampleBounds); - return stats; - } - - SampleStatistics getSampleStatistics() const { - - SampleStatistics sampleStats; - if (numSamples > 0) { - float invNumSamples = 1.f / float(numSamples); - Point3 sampleMean = (Point3(mean.x, mean.y, mean.z) / INTEGER_BINS) * invNumSamples; - Vector3 sampleVariance = (Vector3(variance.x, variance.y, variance.z) / (INTEGER_BINS) ) * invNumSamples; - sampleVariance -= sampleMean * sampleMean; - sampleVariance = Vector3(std::fabs(sampleVariance.x), std::fabs(sampleVariance.y), std::fabs(sampleVariance.z)); + float invNumSamples = 1.f / float(numSamples); + Point3 sampleMean = (Point3(mean.x, mean.y, mean.z) / INTEGER_BINS) * invNumSamples; + Vector3 sampleVariance = (Vector3(variance.x, variance.y, variance.z) / (INTEGER_BINS)) * invNumSamples; + sampleVariance -= sampleMean * sampleMean; + sampleVariance = Vector3(std::fabs(sampleVariance.x), std::fabs(sampleVariance.y), std::fabs(sampleVariance.z)); #ifdef INTERGER_V2 - sampleMean = sampleMean * sampleBoundsHalfExtend; - sampleMean += sampleBoundsCenter; - sampleVariance = sampleVariance * (sampleBoundsHalfExtend * sampleBoundsHalfExtend); + sampleMean = sampleMean * sampleBoundsHalfExtend; + sampleMean += sampleBoundsCenter; + sampleVariance = sampleVariance * (sampleBoundsHalfExtend * sampleBoundsHalfExtend); #else - sampleMean = sampleMean * sampleBoundsExtend; - sampleMean += sampleBoundsMin; - sampleVariance = sampleVariance * (sampleBoundsExtend * sampleBoundsExtend); + sampleMean = sampleMean * sampleBoundsExtend; + sampleMean += sampleBoundsMin; + sampleVariance = sampleVariance * (sampleBoundsExtend * sampleBoundsExtend); #endif - sampleStats.mean = sampleMean; - sampleStats.numSamples = numSamples; - sampleStats.sampleVariance = sampleVariance * float(numSamples); - Point3 sampleBoundLower = Point3(float(sampleBounds.lower.x) - 0.0f, float(sampleBounds.lower.y) - 0.0f, float(sampleBounds.lower.z) - 0.0f) / INTEGER_BINS; + sampleStats.mean = sampleMean; + sampleStats.numSamples = numSamples; + sampleStats.sampleVariance = sampleVariance * float(numSamples); + Point3 sampleBoundLower = Point3(float(sampleBounds.lower.x) - 0.0f, float(sampleBounds.lower.y) - 0.0f, float(sampleBounds.lower.z) - 0.0f) / INTEGER_BINS; #ifdef INTERGER_V2 - sampleBoundLower = sampleBoundLower * sampleBoundsHalfExtend; - sampleBoundLower = sampleBoundLower + sampleBoundsCenter; + sampleBoundLower = sampleBoundLower * sampleBoundsHalfExtend; + sampleBoundLower = sampleBoundLower + sampleBoundsCenter; #else - sampleBoundLower = sampleBoundLower * sampleBoundsExtend; - sampleBoundLower = sampleBoundLower + sampleBoundsMin; + sampleBoundLower = sampleBoundLower * sampleBoundsExtend; + sampleBoundLower = sampleBoundLower + sampleBoundsMin; #endif - - Point3 sampleBoundUpper = Point3(float(sampleBounds.upper.x) + 0.0f, float(sampleBounds.upper.y) + 0.0f, float(sampleBounds.upper.z) + 0.0f) / INTEGER_BINS; + + Point3 sampleBoundUpper = Point3(float(sampleBounds.upper.x) + 0.0f, float(sampleBounds.upper.y) + 0.0f, float(sampleBounds.upper.z) + 0.0f) / INTEGER_BINS; #ifdef INTERGER_V2 - sampleBoundUpper = sampleBoundUpper * sampleBoundsHalfExtend; - sampleBoundUpper = sampleBoundUpper + sampleBoundsCenter; + sampleBoundUpper = sampleBoundUpper * sampleBoundsHalfExtend; + sampleBoundUpper = sampleBoundUpper + sampleBoundsCenter; #else - sampleBoundUpper = sampleBoundUpper * sampleBoundsExtend; - sampleBoundUpper = sampleBoundUpper + sampleBoundsMin; + sampleBoundUpper = sampleBoundUpper * sampleBoundsExtend; + sampleBoundUpper = sampleBoundUpper + sampleBoundsMin; #endif - sampleStats.sampleBounds.lower = sampleBoundLower; - sampleStats.sampleBounds.upper = sampleBoundUpper; - } - return sampleStats; + sampleStats.sampleBounds.lower = sampleBoundLower; + sampleStats.sampleBounds.upper = sampleBoundUpper; } + return sampleStats; + } +}; - }; - -} \ No newline at end of file +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/device/Device.h b/openpgl/device/Device.h index 6ba9e42..01bcbc9 100644 --- a/openpgl/device/Device.h +++ b/openpgl/device/Device.h @@ -1,70 +1,68 @@ #pragma once #include "../include/openpgl/config.h" - #include "../openpgl_common.h" - -#include "field/ISurfaceVolumeField.h" -#include "field/SurfaceVolumeField.h" - -#include "directional/vmm/ParallaxAwareVonMisesFisherMixture.h" -#include "directional/vmm/AdaptiveSplitandMergeFactory.h" -#include "directional/vmm/VMMSurfaceSamplingDistribution.h" -#include "directional/vmm/VMMVolumeSamplingDistribution.h" -#include "directional/vmm/VMMPhaseFunctions.h" #include "directional/dqt/DQT.h" #include "directional/dqt/DQTFactory.h" #include "directional/dqt/DQTSurfaceSamplingDistribution.h" #include "directional/dqt/DQTVolumeSamplingDistribution.h" #include "directional/dqt/SphereToSquare.h" - +#include "directional/vmm/AdaptiveSplitandMergeFactory.h" +#include "directional/vmm/ParallaxAwareVonMisesFisherMixture.h" +#include "directional/vmm/VMMPhaseFunctions.h" +#include "directional/vmm/VMMSurfaceSamplingDistribution.h" +#include "directional/vmm/VMMVolumeSamplingDistribution.h" +#include "field/ISurfaceVolumeField.h" +#include "field/SurfaceVolumeField.h" #include "spatial/kdtree/KDTreeBuilder.h" - #include "tbb/tbb.h" #define OPENPGL_TASK_CONTROL -namespace openpgl { +namespace openpgl +{ #ifdef OPENPGL_TASK_CONTROL #if TBB_INTERFACE_VERSION >= 11005 - static tbb::global_control* g_opgl_tbb_thread_control = nullptr; +static tbb::global_control *g_opgl_tbb_thread_control = nullptr; #else - static tbb::task_scheduler_init g_opgl_tbb_threads(tbb::task_scheduler_init::deferred); +static tbb::task_scheduler_init g_opgl_tbb_threads(tbb::task_scheduler_init::deferred); #endif #endif -struct IDevice { - virtual ~IDevice() {}; - virtual ISurfaceVolumeField* newField(PGLFieldArguments args) const = 0; - virtual ISurfaceVolumeField* newFieldFromFile(const std::string fieldFileName) const = 0; +struct IDevice +{ + virtual ~IDevice(){}; + virtual ISurfaceVolumeField *newField(PGLFieldArguments args) const = 0; + virtual ISurfaceVolumeField *newFieldFromFile(const std::string fieldFileName) const = 0; }; -template -struct Device: public IDevice { - -private: +template +struct Device : public IDevice +{ + private: #ifdef OPENPGL_TASK_CONTROL - size_t m_numThreads {0}; + size_t m_numThreads{0}; #endif -public: + public: Device(size_t numThreads = 0) { #ifdef OPENPGL_TASK_CONTROL - if (numThreads == 0) + if (numThreads == 0) { #if TBB_INTERFACE_VERSION >= 9100 m_numThreads = tbb::this_task_arena::max_concurrency(); #else m_numThreads = tbb::task_scheduler_init::default_num_threads(); #endif - } else { + } + else + { #if TBB_INTERFACE_VERSION >= 9100 m_numThreads = std::min(numThreads, (size_t)tbb::this_task_arena::max_concurrency()); #else m_numThreads = std::min(numThreads, (size_t)tbb::task_scheduler_init::default_num_threads()); #endif - } #if TBB_INTERFACE_VERSION >= 11005 g_opgl_tbb_thread_control = new tbb::global_control(tbb::global_control::max_allowed_parallelism, m_numThreads); @@ -87,29 +85,31 @@ struct Device: public IDevice { #endif } - ISurfaceVolumeField* newField(PGLFieldArguments args) const override { - ISurfaceVolumeField* gField; + ISurfaceVolumeField *newField(PGLFieldArguments args) const override + { + ISurfaceVolumeField *gField; - if (args.spatialStructureType == PGL_SPATIAL_STRUCTURE_KDTREE && - args.directionalDistributionType == PGL_DIRECTIONAL_DISTRIBUTION_PARALLAX_AWARE_VMM ) + if (args.spatialStructureType == PGL_SPATIAL_STRUCTURE_KDTREE && args.directionalDistributionType == PGL_DIRECTIONAL_DISTRIBUTION_PARALLAX_AWARE_VMM) { using DirectionalDistributionFactory = AdaptiveSplitAndMergeFactory>; - using GuidingField = SurfaceVolumeField, VMMVolumeSamplingDistribution>; + using GuidingField = SurfaceVolumeField, + VMMVolumeSamplingDistribution>; typename GuidingField::Settings gFieldSettings; - gFieldSettings.settings.decayOnSpatialSplit = 0.25f; - gFieldSettings.settings.deterministic = args.deterministic; - gFieldSettings.debugSettings.fitRegions = args.debugArguments.fitRegions; + gFieldSettings.settings.decayOnSpatialSplit = 0.25f; + gFieldSettings.settings.deterministic = args.deterministic; + gFieldSettings.debugSettings.fitRegions = args.debugArguments.fitRegions; - PGLKDTreeArguments *spatialSturctureArguments = (PGLKDTreeArguments*)args.spatialSturctureArguments; + PGLKDTreeArguments *spatialSturctureArguments = (PGLKDTreeArguments *)args.spatialSturctureArguments; gFieldSettings.settings.useStochasticNNLookUp = spatialSturctureArguments->knnLookup; gFieldSettings.settings.useISNNLookUp = spatialSturctureArguments->isKnnLookup; gFieldSettings.settings.spatialSubdivBuilderSettings.minSamples = spatialSturctureArguments->minSamples; gFieldSettings.settings.spatialSubdivBuilderSettings.maxSamples = spatialSturctureArguments->maxSamples; - gFieldSettings.settings.spatialSubdivBuilderSettings.maxDepth = spatialSturctureArguments->maxDepth; + gFieldSettings.settings.spatialSubdivBuilderSettings.maxDepth = spatialSturctureArguments->maxDepth; delete spatialSturctureArguments; - PGLVMMFactoryArguments *directionalDistributionArguments = (PGLVMMFactoryArguments*)args.directionalDistributionArguments; + PGLVMMFactoryArguments *directionalDistributionArguments = (PGLVMMFactoryArguments *)args.directionalDistributionArguments; gFieldSettings.distributionFactorySettings.weightedEMCfg.initK = directionalDistributionArguments->initK; gFieldSettings.distributionFactorySettings.weightedEMCfg.initKappa = directionalDistributionArguments->initKappa; @@ -117,7 +117,8 @@ struct Device: public IDevice { gFieldSettings.distributionFactorySettings.weightedEMCfg.maxEMIterrations = directionalDistributionArguments->maxEMIterrations; gFieldSettings.distributionFactorySettings.weightedEMCfg.maxKappa = directionalDistributionArguments->maxKappa; - gFieldSettings.distributionFactorySettings.weightedEMCfg.maxMeanCosine = openpgl::KappaToMeanCosine(gFieldSettings.distributionFactorySettings.weightedEMCfg.maxKappa); + gFieldSettings.distributionFactorySettings.weightedEMCfg.maxMeanCosine = + openpgl::KappaToMeanCosine(gFieldSettings.distributionFactorySettings.weightedEMCfg.maxKappa); gFieldSettings.distributionFactorySettings.weightedEMCfg.convergenceThreshold = directionalDistributionArguments->convergenceThreshold; gFieldSettings.distributionFactorySettings.weightedEMCfg.weightPrior = directionalDistributionArguments->weightPrior; gFieldSettings.distributionFactorySettings.weightedEMCfg.meanCosinePriorStrength = directionalDistributionArguments->meanCosinePriorStrength; @@ -126,7 +127,6 @@ struct Device: public IDevice { gFieldSettings.distributionFactorySettings.splittingThreshold = directionalDistributionArguments->splittingThreshold; gFieldSettings.distributionFactorySettings.mergingThreshold = directionalDistributionArguments->mergingThreshold; - gFieldSettings.distributionFactorySettings.partialReFit = directionalDistributionArguments->partialReFit; gFieldSettings.distributionFactorySettings.maxSplitItr = directionalDistributionArguments->maxSplitItr; @@ -137,26 +137,28 @@ struct Device: public IDevice { delete directionalDistributionArguments; gField = new GuidingField(gFieldSettings); - } else if (args.spatialStructureType == PGL_SPATIAL_STRUCTURE_KDTREE && - args.directionalDistributionType == PGL_DIRECTIONAL_DISTRIBUTION_VMM ) + } + else if (args.spatialStructureType == PGL_SPATIAL_STRUCTURE_KDTREE && args.directionalDistributionType == PGL_DIRECTIONAL_DISTRIBUTION_VMM) { using DirectionalDistributionFactory = AdaptiveSplitAndMergeFactory>; - using GuidingField = SurfaceVolumeField, VMMVolumeSamplingDistribution>; + using GuidingField = SurfaceVolumeField, + VMMVolumeSamplingDistribution>; typename GuidingField::Settings gFieldSettings; - gFieldSettings.settings.decayOnSpatialSplit = 0.25f; - gFieldSettings.settings.deterministic = args.deterministic; - gFieldSettings.debugSettings.fitRegions = args.debugArguments.fitRegions; + gFieldSettings.settings.decayOnSpatialSplit = 0.25f; + gFieldSettings.settings.deterministic = args.deterministic; + gFieldSettings.debugSettings.fitRegions = args.debugArguments.fitRegions; - PGLKDTreeArguments *spatialSturctureArguments = (PGLKDTreeArguments*)args.spatialSturctureArguments; + PGLKDTreeArguments *spatialSturctureArguments = (PGLKDTreeArguments *)args.spatialSturctureArguments; gFieldSettings.settings.useStochasticNNLookUp = spatialSturctureArguments->knnLookup; gFieldSettings.settings.useISNNLookUp = spatialSturctureArguments->isKnnLookup; gFieldSettings.settings.spatialSubdivBuilderSettings.minSamples = spatialSturctureArguments->minSamples; gFieldSettings.settings.spatialSubdivBuilderSettings.maxSamples = spatialSturctureArguments->maxSamples; - gFieldSettings.settings.spatialSubdivBuilderSettings.maxDepth = spatialSturctureArguments->maxDepth; + gFieldSettings.settings.spatialSubdivBuilderSettings.maxDepth = spatialSturctureArguments->maxDepth; delete spatialSturctureArguments; - PGLVMMFactoryArguments *directionalDistributionArguments = (PGLVMMFactoryArguments*)args.directionalDistributionArguments; + PGLVMMFactoryArguments *directionalDistributionArguments = (PGLVMMFactoryArguments *)args.directionalDistributionArguments; gFieldSettings.distributionFactorySettings.weightedEMCfg.initK = directionalDistributionArguments->initK; gFieldSettings.distributionFactorySettings.weightedEMCfg.initKappa = directionalDistributionArguments->initKappa; @@ -164,7 +166,8 @@ struct Device: public IDevice { gFieldSettings.distributionFactorySettings.weightedEMCfg.maxEMIterrations = directionalDistributionArguments->maxEMIterrations; gFieldSettings.distributionFactorySettings.weightedEMCfg.maxKappa = directionalDistributionArguments->maxKappa; - gFieldSettings.distributionFactorySettings.weightedEMCfg.maxMeanCosine = openpgl::KappaToMeanCosine(gFieldSettings.distributionFactorySettings.weightedEMCfg.maxKappa); + gFieldSettings.distributionFactorySettings.weightedEMCfg.maxMeanCosine = + openpgl::KappaToMeanCosine(gFieldSettings.distributionFactorySettings.weightedEMCfg.maxKappa); gFieldSettings.distributionFactorySettings.weightedEMCfg.convergenceThreshold = directionalDistributionArguments->convergenceThreshold; gFieldSettings.distributionFactorySettings.weightedEMCfg.weightPrior = directionalDistributionArguments->weightPrior; gFieldSettings.distributionFactorySettings.weightedEMCfg.meanCosinePriorStrength = directionalDistributionArguments->meanCosinePriorStrength; @@ -173,7 +176,6 @@ struct Device: public IDevice { gFieldSettings.distributionFactorySettings.splittingThreshold = directionalDistributionArguments->splittingThreshold; gFieldSettings.distributionFactorySettings.mergingThreshold = directionalDistributionArguments->mergingThreshold; - gFieldSettings.distributionFactorySettings.partialReFit = directionalDistributionArguments->partialReFit; gFieldSettings.distributionFactorySettings.maxSplitItr = directionalDistributionArguments->maxSplitItr; @@ -184,25 +186,27 @@ struct Device: public IDevice { delete directionalDistributionArguments; gField = new GuidingField(gFieldSettings); - } else if (args.spatialStructureType == PGL_SPATIAL_STRUCTURE_KDTREE && - args.directionalDistributionType == PGL_DIRECTIONAL_DISTRIBUTION_QUADTREE ) + } + else if (args.spatialStructureType == PGL_SPATIAL_STRUCTURE_KDTREE && args.directionalDistributionType == PGL_DIRECTIONAL_DISTRIBUTION_QUADTREE) { using DirectionalDistributionFactory = DirectionalQuadtreeFactory>; - using GuidingField = SurfaceVolumeField, DQTVolumeSamplingDistribution>; + using GuidingField = + SurfaceVolumeField, + DQTVolumeSamplingDistribution>; typename GuidingField::Settings gFieldSettings; - gFieldSettings.settings.decayOnSpatialSplit = 0.25f; - gFieldSettings.settings.deterministic = args.deterministic; - gFieldSettings.debugSettings.fitRegions = args.debugArguments.fitRegions; + gFieldSettings.settings.decayOnSpatialSplit = 0.25f; + gFieldSettings.settings.deterministic = args.deterministic; + gFieldSettings.debugSettings.fitRegions = args.debugArguments.fitRegions; - PGLKDTreeArguments *spatialSturctureArguments = (PGLKDTreeArguments*)args.spatialSturctureArguments; + PGLKDTreeArguments *spatialSturctureArguments = (PGLKDTreeArguments *)args.spatialSturctureArguments; gFieldSettings.settings.useStochasticNNLookUp = spatialSturctureArguments->knnLookup; gFieldSettings.settings.useISNNLookUp = spatialSturctureArguments->isKnnLookup; gFieldSettings.settings.spatialSubdivBuilderSettings.minSamples = spatialSturctureArguments->minSamples; gFieldSettings.settings.spatialSubdivBuilderSettings.maxSamples = spatialSturctureArguments->maxSamples; - gFieldSettings.settings.spatialSubdivBuilderSettings.maxDepth = spatialSturctureArguments->maxDepth; + gFieldSettings.settings.spatialSubdivBuilderSettings.maxDepth = spatialSturctureArguments->maxDepth; - PGLDQTFactoryArguments *directionalDistributionArguments = (PGLDQTFactoryArguments*)args.directionalDistributionArguments; + PGLDQTFactoryArguments *directionalDistributionArguments = (PGLDQTFactoryArguments *)args.directionalDistributionArguments; gFieldSettings.distributionFactorySettings.leafEstimator = (LeafEstimator)directionalDistributionArguments->leafEstimator; gFieldSettings.distributionFactorySettings.splitMetric = (SplitMetric)directionalDistributionArguments->splitMetric; gFieldSettings.distributionFactorySettings.splitThreshold = directionalDistributionArguments->splitThreshold; @@ -210,58 +214,72 @@ struct Device: public IDevice { gFieldSettings.distributionFactorySettings.maxLevels = directionalDistributionArguments->maxLevels; gField = new GuidingField(gFieldSettings); - }else { + } + else + { throw std::runtime_error("error: unrecognized field type"); } return gField; } - ISurfaceVolumeField* newFieldFromFile(const std::string fieldFileName) const override { + ISurfaceVolumeField *newFieldFromFile(const std::string fieldFileName) const override + { std::filebuf fb; - fb.open (fieldFileName, std::ios::in | std::ios::binary); - if (!fb.is_open()) throw std::runtime_error("error: couldn't open file"); + fb.open(fieldFileName, std::ios::in | std::ios::binary); + if (!fb.is_open()) + throw std::runtime_error("error: couldn't open file"); std::istream is(&fb); auto size = strlen(FIELD_FILE_HEADER_STRING) + 1; OPENPGL_ASSERT(size <= 256); char buf[256]; is.read(&buf[0], size); - if (!is) throw std::runtime_error("error: invalid file header"); -#ifdef OPENPGL_STRICT_IO_VERSION_CHECKING + if (!is) + throw std::runtime_error("error: invalid file header"); +#ifdef OPENPGL_STRICT_IO_VERSION_CHECKING for (auto i = 0; i < size; i++) { if (buf[i] != FIELD_FILE_HEADER_STRING[i]) throw std::runtime_error("error: invalid file header"); } -#endif +#endif PGL_SPATIAL_STRUCTURE_TYPE spatialStructureType; - is.read(reinterpret_cast(&spatialStructureType), sizeof(spatialStructureType)); + is.read(reinterpret_cast(&spatialStructureType), sizeof(spatialStructureType)); PGL_DIRECTIONAL_DISTRIBUTION_TYPE directionalDistributionType; - is.read(reinterpret_cast(&directionalDistributionType), sizeof(directionalDistributionType)); + is.read(reinterpret_cast(&directionalDistributionType), sizeof(directionalDistributionType)); - ISurfaceVolumeField* gField; + ISurfaceVolumeField *gField; if (spatialStructureType == PGL_SPATIAL_STRUCTURE_KDTREE && directionalDistributionType == PGL_DIRECTIONAL_DISTRIBUTION_PARALLAX_AWARE_VMM) { using DirectionalDistributionFactory = AdaptiveSplitAndMergeFactory>; - using GuidingField = SurfaceVolumeField, VMMVolumeSamplingDistribution>; + using GuidingField = SurfaceVolumeField, + VMMVolumeSamplingDistribution>; gField = (ISurfaceVolumeField *)new GuidingField(); - } else if (spatialStructureType == PGL_SPATIAL_STRUCTURE_KDTREE && directionalDistributionType == PGL_DIRECTIONAL_DISTRIBUTION_VMM) + } + else if (spatialStructureType == PGL_SPATIAL_STRUCTURE_KDTREE && directionalDistributionType == PGL_DIRECTIONAL_DISTRIBUTION_VMM) { using DirectionalDistributionFactory = AdaptiveSplitAndMergeFactory>; - using GuidingField = SurfaceVolumeField, VMMVolumeSamplingDistribution>; + using GuidingField = SurfaceVolumeField, + VMMVolumeSamplingDistribution>; gField = (ISurfaceVolumeField *)new GuidingField(); - } else if (spatialStructureType == PGL_SPATIAL_STRUCTURE_KDTREE && - directionalDistributionType == PGL_DIRECTIONAL_DISTRIBUTION_QUADTREE) + } + else if (spatialStructureType == PGL_SPATIAL_STRUCTURE_KDTREE && directionalDistributionType == PGL_DIRECTIONAL_DISTRIBUTION_QUADTREE) { using DirectionalDistributionFactory = DirectionalQuadtreeFactory>; - using GuidingField = SurfaceVolumeField, DQTVolumeSamplingDistribution>; + using GuidingField = + SurfaceVolumeField, + DQTVolumeSamplingDistribution>; gField = (ISurfaceVolumeField *)new GuidingField(); - } else { + } + else + { fb.close(); throw std::runtime_error("error: unrecognized field type"); } @@ -275,15 +293,15 @@ struct Device: public IDevice { }; #ifdef OPENPGL_DEVICE_TYPE_CPU_4 -IDevice* newDeviceCPU4(size_t numThreads = 0); +IDevice *newDeviceCPU4(size_t numThreads = 0); #endif #ifdef OPENPGL_DEVICE_TYPE_CPU_8 -IDevice* newDeviceCPU8(size_t numThreads = 0); +IDevice *newDeviceCPU8(size_t numThreads = 0); #endif #ifdef OPENPGL_DEVICE_TYPE_CPU_16 -IDevice* newDeviceCPU16(size_t numThreads = 0); +IDevice *newDeviceCPU16(size_t numThreads = 0); #endif -} +} // namespace openpgl #undef FILE_HEADER_STRING diff --git a/openpgl/directional/DirectionalDistributionStatistics.h b/openpgl/directional/DirectionalDistributionStatistics.h index ad85147..e524b4e 100644 --- a/openpgl/directional/DirectionalDistributionStatistics.h +++ b/openpgl/directional/DirectionalDistributionStatistics.h @@ -3,23 +3,25 @@ #pragma once -#include "../openpgl_common.h" - #include -#include #include +#include + +#include "../openpgl_common.h" namespace openpgl { -struct DirectionalDistributionStatistics{ - size_t sizePerDistribution {0}; - float minNumberOfComponents {0}; - float maxNumberOfComponents {0}; - float averageNumberOfComponents {0}; - float secondMomentNumberOfComponents {0}; - - std::string headerCSVString() const { +struct DirectionalDistributionStatistics +{ + size_t sizePerDistribution{0}; + float minNumberOfComponents{0}; + float maxNumberOfComponents{0}; + float averageNumberOfComponents{0}; + float secondMomentNumberOfComponents{0}; + + std::string headerCSVString() const + { const std::string separator = " , "; std::stringstream ss; ss << "DirectionalDistributionStatistics:" << separator; @@ -31,7 +33,8 @@ struct DirectionalDistributionStatistics{ return ss.str(); } - std::string toCSVString() const { + std::string toCSVString() const + { const std::string separator = " , "; std::stringstream ss; ss << " " << separator; @@ -43,11 +46,12 @@ struct DirectionalDistributionStatistics{ return ss.str(); } - std::string toString() const { + std::string toString() const + { const std::string tab = "\t"; std::stringstream ss; ss << "DirectionalDistributionStatistics: " << std::endl; - ss << tab << "sizePerDistribution = " << sizePerDistribution << " bs"< -#include #include +#include +#include -#include "Traversal.h" +#include "../../openpgl_common.h" #include "Rect.h" +#include "Traversal.h" -namespace openpgl { - struct DirectionalQuadtreeNode { - uint32_t offsetChildren = 0; - float sampleWeight = 0; - - std::string toString() const { - std::stringstream ss; - ss << "DirectionalQuadtreeNode:" << std::endl; - ss << "\toffsetChildren = " << offsetChildren << std::endl; - ss << "\tsampleWeight = " << sampleWeight << std::endl; - return ss.str(); - } +namespace openpgl +{ +struct DirectionalQuadtreeNode +{ + uint32_t offsetChildren = 0; + float sampleWeight = 0; + + std::string toString() const + { + std::stringstream ss; + ss << "DirectionalQuadtreeNode:" << std::endl; + ss << "\toffsetChildren = " << offsetChildren << std::endl; + ss << "\tsampleWeight = " << sampleWeight << std::endl; + return ss.str(); + } +}; + +template +struct DirectionalQuadtree +{ + enum + { + ParallaxCompensation = 0 }; - template - struct DirectionalQuadtree { - - enum { - ParallaxCompensation = 0 - }; - - using Sphere2Square = TSphere2Square; - - Point3 _pivotPosition; - std::vector nodes = { DirectionalQuadtreeNode() }; - - DirectionalQuadtree() = default; - - // Public Interface - inline bool isValid() const { - return !std::isinf(nodes[0].sampleWeight) && nodes[0].sampleWeight > 0; - } - - inline Vector3 sample(const Vector2 sample) const { - OPENPGL_ASSERT(isValid()); - OPENPGL_ASSERT(0 <= sample.x && sample.x <= 1 && 0 <= sample.y && sample.y <= 1); + using Sphere2Square = TSphere2Square; + + Point3 _pivotPosition; + std::vector nodes = {DirectionalQuadtreeNode()}; + + DirectionalQuadtree() = default; + + // Public Interface + inline bool isValid() const + { + return !std::isinf(nodes[0].sampleWeight) && nodes[0].sampleWeight > 0; + } + + inline Vector3 sample(const Vector2 sample) const + { + OPENPGL_ASSERT(isValid()); + OPENPGL_ASSERT(0 <= sample.x && sample.x <= 1 && 0 <= sample.y && sample.y <= 1); + + float pdf; + Vector2 point = sampleQuadtree(sample, pdf); + return Sphere2Square::pointToDirection(point); + } + + inline float pdf(const Vector3 direction) const + { + OPENPGL_ASSERT(isValid()); + + Vector2 point = Sphere2Square::directionToPoint(direction); + float pdf = std::min(FLT_MAX, pdfQuadtree(point) / Sphere2Square::jacobian(point)); + OPENPGL_ASSERT(pdf > 0); + return pdf; + } + + inline float samplePdf(const Vector2 sample, Vector3 &dir) const + { + OPENPGL_ASSERT(isValid()); + OPENPGL_ASSERT(0 <= sample.x && sample.x <= 1 && 0 <= sample.y && sample.y <= 1); + + float pdf; + Vector2 point = sampleQuadtree(sample, pdf); + pdf /= Sphere2Square::jacobian(point); + OPENPGL_ASSERT(pdf > 0); + dir = Sphere2Square::pointToDirection(point); + return pdf; + } + + void performRelativeParallaxShift(const Vector3 &shiftDirection) {}; + + const std::string toString() const + { + std::stringstream out; + + out << "DirectionalQuadtree [" << std::endl; + for (int i = 0; i < nodes.size(); i++) + out << i << ": " << nodes[i].toString(); + out << "]" << std::endl; + + return out.str(); + } + + void serialize(std::ostream &os) const + { + os.write(reinterpret_cast(&_pivotPosition), sizeof(_pivotPosition)); + size_t size = nodes.size(); + os.write(reinterpret_cast(&size), sizeof(size)); + os.write(reinterpret_cast(nodes.data()), size * sizeof(nodes[0])); + }; - float pdf; - Vector2 point = sampleQuadtree(sample, pdf); - return Sphere2Square::pointToDirection(point); - } + void deserialize(std::istream &is) + { + is.read(reinterpret_cast(&_pivotPosition), sizeof(_pivotPosition)); + size_t size; + is.read(reinterpret_cast(&size), sizeof(size)); + nodes = std::vector(size); + is.read(reinterpret_cast(nodes.data()), size * sizeof(nodes[0])); + }; - inline float pdf(const Vector3 direction) const { - OPENPGL_ASSERT(isValid()); + void decay(const float alpha) {}; - Vector2 point = Sphere2Square::directionToPoint(direction); - float pdf = std::min(FLT_MAX, pdfQuadtree(point) / Sphere2Square::jacobian(point)); - OPENPGL_ASSERT(pdf > 0); - return pdf; - } + size_t getNumComponents() const + { + return nodes.size(); + } - inline float samplePdf(const Vector2 sample, Vector3 &dir) const { - OPENPGL_ASSERT(isValid()); - OPENPGL_ASSERT(0 <= sample.x && sample.x <= 1 && 0 <= sample.y && sample.y <= 1); + // TODO: Needs to be implmented + bool operator==(const DirectionalQuadtree &b) const + { + return true; + } - float pdf; - Vector2 point = sampleQuadtree(sample, pdf); - pdf /= Sphere2Square::jacobian(point); - OPENPGL_ASSERT(pdf > 0); - dir = Sphere2Square::pointToDirection(point); - return pdf; - } + private: + // Internal Sampling Routines + // TODO prepare weights so that no rescaling needed? (i.e. three thresholds per cell) + inline Vector2 sampleQuadtree(const Vector2 sample, float &pdf) const + { + // perform stochastic top-down traveral, according to sampling weights of nodes + Vector2 random = sample; - void performRelativeParallaxShift( const Vector3 &shiftDirection) {}; + float span = 1; + Vector2 point(0, 0); - const std::string toString() const + const DirectionalQuadtreeNode *node = &nodes[0]; + while (node->offsetChildren > 0) { - std::stringstream out; - - out << "DirectionalQuadtree [" << std::endl; - for (int i = 0; i < nodes.size(); i++) - out << i << ": " << nodes[i].toString(); - out << "]" << std::endl; - - return out.str(); - } - - void serialize(std::ostream& os) const{ - os.write(reinterpret_cast(&_pivotPosition), sizeof(_pivotPosition)); - size_t size = nodes.size(); - os.write(reinterpret_cast(&size), sizeof(size)); - os.write(reinterpret_cast(nodes.data()), size * sizeof(nodes[0])); + span /= 2; + uint32_t offset = 0; + const DirectionalQuadtreeNode *children = &nodes[node->offsetChildren]; + + float weightLeft = children[0].sampleWeight + children[2].sampleWeight; + float weightRight = children[1].sampleWeight + children[3].sampleWeight; + OPENPGL_ASSERT(weightLeft + weightRight > 0); + float probabilityLeft = weightLeft / (weightLeft + weightRight); + + if (!rescale(probabilityLeft, random.x)) + { + offset += 1; + point.x += span; + } + + float weightTop = children[offset + 0].sampleWeight; + float weightBottom = children[offset + 2].sampleWeight; + OPENPGL_ASSERT(weightTop + weightBottom > 0); + float probabilityTop = weightTop / (weightTop + weightBottom); + + if (!rescale(probabilityTop, random.y)) + { + offset += 2; + point.y += span; + } + + node = &children[offset]; }; - void deserialize(std::istream& is){ - is.read(reinterpret_cast(&_pivotPosition), sizeof(_pivotPosition)); - size_t size; - is.read(reinterpret_cast(&size), sizeof(size)); - nodes = std::vector(size); - is.read(reinterpret_cast(nodes.data()), size * sizeof(nodes[0])); - }; - - void decay(const float alpha) - {}; - - size_t getNumComponents() const{ - return nodes.size(); - } - - // TODO: Needs to be implmented - bool operator==(const DirectionalQuadtree& b) const { - return true; - } - - private: - // Internal Sampling Routines - // TODO prepare weights so that no rescaling needed? (i.e. three thresholds per cell) - inline Vector2 sampleQuadtree(const Vector2 sample, float &pdf) const { - // perform stochastic top-down traveral, according to sampling weights of nodes - Vector2 random = sample; - - float span = 1; - Vector2 point(0, 0); - - const DirectionalQuadtreeNode* node = &nodes[0]; - while (node->offsetChildren > 0) { - span /= 2; - uint32_t offset = 0; - const DirectionalQuadtreeNode* children = &nodes[node->offsetChildren]; - - float weightLeft = children[0].sampleWeight + children[2].sampleWeight; - float weightRight = children[1].sampleWeight + children[3].sampleWeight; - OPENPGL_ASSERT(weightLeft + weightRight > 0); - float probabilityLeft = weightLeft / (weightLeft + weightRight); - - if (!rescale(probabilityLeft, random.x)) { - offset += 1; - point.x += span; - } - - float weightTop = children[offset + 0].sampleWeight; - float weightBottom = children[offset + 2].sampleWeight; - OPENPGL_ASSERT(weightTop + weightBottom > 0); - float probabilityTop = weightTop / (weightTop + weightBottom); - - if (!rescale(probabilityTop, random.y)) { - offset += 2; - point.y += span; - } - - node = &children[offset]; - }; - - pdf = node->sampleWeight / (nodes[0].sampleWeight * span * span); - return point + random * span; - } - - inline float pdfQuadtree(Vector2 point) const { - Rect rect; - auto node_idx = queryNode(nodes.data(), point, rect); - return nodes[node_idx].sampleWeight / (nodes[0].sampleWeight * rect.area()); - } - }; -} \ No newline at end of file + pdf = node->sampleWeight / (nodes[0].sampleWeight * span * span); + return point + random * span; + } + + inline float pdfQuadtree(Vector2 point) const + { + Rect rect; + auto node_idx = queryNode(nodes.data(), point, rect); + return nodes[node_idx].sampleWeight / (nodes[0].sampleWeight * rect.area()); + } +}; +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/directional/dqt/DQTFactory.h b/openpgl/directional/dqt/DQTFactory.h index 1390659..cc4e889 100644 --- a/openpgl/directional/dqt/DQTFactory.h +++ b/openpgl/directional/dqt/DQTFactory.h @@ -1,37 +1,42 @@ #pragma once -#include "../../openpgl_common.h" +#include +#include + #include "../../data/SampleData.h" #include "../../data/SampleStatistics.h" #include "../../include/openpgl/types.h" -#include -#include - +#include "../../openpgl_common.h" #include "DQT.h" -#include "Traversal.h" #include "Rect.h" +#include "Traversal.h" -namespace openpgl { +namespace openpgl +{ -enum LeafEstimator { +enum LeafEstimator +{ REJECTION_SAMPLING = 0, PER_LEAF, }; -enum SplitMetric { +enum SplitMetric +{ MEAN = 0, SECOND_MOMENT, }; -template -class DirectionalQuadtreeFactory { -public: +template +class DirectionalQuadtreeFactory +{ + public: const static PGL_DIRECTIONAL_DISTRIBUTION_TYPE DIRECTIONAL_DISTRIBUTION_TYPE = PGL_DIRECTIONAL_DISTRIBUTION_QUADTREE; using Distribution = TDistribution; using Sphere2Square = typename Distribution::Sphere2Square; - struct Configuration { + struct Configuration + { // Estimator for the incoming radiance (and second moment thereof) of each leaf. // REJECTION_SAMPLING // Accumulate samples (contribution / pdf) into quadtree leaves, @@ -57,20 +62,24 @@ class DirectionalQuadtreeFactory { uint32_t maxLevels = 12; - void serialize(std::ostream& stream) const { - stream.write(reinterpret_cast(this), sizeof(*this)); + void serialize(std::ostream &stream) const + { + stream.write(reinterpret_cast(this), sizeof(*this)); }; - void deserialize(std::istream& stream) { - stream.read(reinterpret_cast(this), sizeof(*this)); + void deserialize(std::istream &stream) + { + stream.read(reinterpret_cast(this), sizeof(*this)); }; - bool operator==(const Configuration& b) const { + bool operator==(const Configuration &b) const + { return true; } }; - struct StatsNode { + struct StatsNode + { uint32_t offsetChildren = 0; float sampleWeight = 0.f; @@ -81,11 +90,14 @@ class DirectionalQuadtreeFactory { float secondMoment = 0.f; }; - struct Statistics { + struct Statistics + { // TODO this is very ugly - struct SufficientStatistics { + struct SufficientStatistics + { void applyParallaxShift(const Distribution &dist, const Vector3 shift) {} - bool isValid() const { + bool isValid() const + { return true; } } sufficientStatistics; @@ -93,75 +105,89 @@ class DirectionalQuadtreeFactory { float numSamples = 0; std::vector nodes = {StatsNode()}; - bool isValid() const { + bool isValid() const + { auto valid = [](float number) { return !std::isnan(number) && !std::isinf(number) && number >= 0; }; - for (auto &node : nodes) { - if (!valid(node.sampleWeight)) return false; - if (!valid(node.splitWeight)) return false; - if (!valid(node.numSamples)) return false; - if (!valid(node.firstMoment)) return false; - if (!valid(node.secondMoment)) return false; + for (auto &node : nodes) + { + if (!valid(node.sampleWeight)) + return false; + if (!valid(node.splitWeight)) + return false; + if (!valid(node.numSamples)) + return false; + if (!valid(node.firstMoment)) + return false; + if (!valid(node.secondMoment)) + return false; } return nodes[0].sampleWeight > 0 && nodes[0].splitWeight > 0; } - void decay(float &alpha) { + void decay(float &alpha) + { numSamples *= alpha; - for (auto &node : nodes) { + for (auto &node : nodes) + { node.numSamples *= alpha; node.firstMoment *= alpha; node.secondMoment *= alpha; } } - void serialize(std::ostream& os) const { - os.write(reinterpret_cast(&numSamples), sizeof(numSamples)); + void serialize(std::ostream &os) const + { + os.write(reinterpret_cast(&numSamples), sizeof(numSamples)); size_t size = nodes.size(); - os.write(reinterpret_cast(&size), sizeof(size)); - os.write(reinterpret_cast(nodes.data()), size * sizeof(nodes[0])); + os.write(reinterpret_cast(&size), sizeof(size)); + os.write(reinterpret_cast(nodes.data()), size * sizeof(nodes[0])); }; - void deserialize(std::istream& is) { - is.read(reinterpret_cast(&numSamples), sizeof(numSamples)); + void deserialize(std::istream &is) + { + is.read(reinterpret_cast(&numSamples), sizeof(numSamples)); size_t size; - is.read(reinterpret_cast(&size), sizeof(size)); + is.read(reinterpret_cast(&size), sizeof(size)); nodes = std::vector(size); - is.read(reinterpret_cast(nodes.data()), size * sizeof(nodes[0])); + is.read(reinterpret_cast(nodes.data()), size * sizeof(nodes[0])); }; // TODO: Needs to be implmented - bool operator==(const Statistics& b) const { + bool operator==(const Statistics &b) const + { return true; } }; - struct FittingStatistics { + struct FittingStatistics + { uint32_t numSamples = 0; uint32_t numNodes = 0; uint32_t numSplits = 0; uint32_t numMerges = 0; }; - void prepareSamples(SampleData* samples, const size_t numSamples, const SampleStatistics &sampleStatistics, const Configuration &cfg) const - {} + void prepareSamples(SampleData *samples, const size_t numSamples, const SampleStatistics &sampleStatistics, const Configuration &cfg) const {} - void updateFluenceEstimate(Distribution &dist, const SampleData* samples, const size_t numSamples, const size_t numZeroValueSamples, const SampleStatistics &sampleStatistics) const + void updateFluenceEstimate(Distribution &dist, const SampleData *samples, const size_t numSamples, const size_t numZeroValueSamples, + const SampleStatistics &sampleStatistics) const {} - void fit(Distribution &dist, Statistics &stats, const SampleData* samples, const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) { - for (uint32_t i = 0; i < 5; i++) { + void fit(Distribution &dist, Statistics &stats, const SampleData *samples, const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) + { + for (uint32_t i = 0; i < 5; i++) + { float decay = 0.25; stats.decay(decay); update(dist, stats, samples, numSamples, cfg, fitStats); } } - void update(Distribution &dist, Statistics &stats, const SampleData* samples, const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) { - Context ctx = { - &dist, &stats, &fitStats, samples, numSamples, &cfg - }; + void update(Distribution &dist, Statistics &stats, const SampleData *samples, const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) + { + Context ctx = {&dist, &stats, &fitStats, samples, numSamples, &cfg}; auto leafEstimator = ctx.cfg->leafEstimator; auto splitMetric = ctx.cfg->splitMetric; @@ -188,23 +214,27 @@ class DirectionalQuadtreeFactory { else if (leafEstimator == LeafEstimator::PER_LEAF && splitMetric == SplitMetric::SECOND_MOMENT && footprintFactor > 0) updateInternal(ctx); } -private: - struct Context { - Distribution* dist; - Statistics* stats; - FittingStatistics* fitStats; - const SampleData* samples; + + private: + struct Context + { + Distribution *dist; + Statistics *stats; + FittingStatistics *fitStats; + const SampleData *samples; const size_t numSamples; - const Configuration* cfg; + const Configuration *cfg; }; // Internal Update Routines - template - void updateInternal(Context &ctx) { + template + void updateInternal(Context &ctx) + { ctx.fitStats->numSamples = ctx.stats->numSamples += ctx.numSamples; // Accumulate all samples into leaves - for (uint32_t i = 0; i < ctx.numSamples; i++) { + for (uint32_t i = 0; i < ctx.numSamples; i++) + { const auto &sample = ctx.samples[i]; OPENPGL_ASSERT(isValid(sample)); @@ -212,11 +242,13 @@ class DirectionalQuadtreeFactory { float firstMoment = 0, secondMoment = 0; // TODO use if constexpr when we start using c++17 - if (TLeafEstimator == LeafEstimator::REJECTION_SAMPLING) { + if (TLeafEstimator == LeafEstimator::REJECTION_SAMPLING) + { firstMoment = sample.weight; secondMoment = sample.weight * sample.weight * sample.pdf; } - if (TLeafEstimator == LeafEstimator::PER_LEAF) { + if (TLeafEstimator == LeafEstimator::PER_LEAF) + { firstMoment = sample.weight * sample.pdf; secondMoment = firstMoment * firstMoment; } @@ -231,21 +263,26 @@ class DirectionalQuadtreeFactory { } // Compute sampling and split weights - traverse(ctx.stats->nodes.data(), + traverse( + ctx.stats->nodes.data(), [&](uint32_t i, Rect &rect) { - return true; // We want to traverse all nodes + return true; // We want to traverse all nodes }, [&](uint32_t i, Rect &rect) { auto &node = ctx.stats->nodes[i]; - if (node.offsetChildren > 0) { + if (node.offsetChildren > 0) + { node.sampleWeight = 0; node.splitWeight = 0; - for (uint32_t i = 0; i < 4; i++) { + for (uint32_t i = 0; i < 4; i++) + { StatsNode &child_node = ctx.stats->nodes[node.offsetChildren + i]; node.sampleWeight += child_node.sampleWeight; node.splitWeight += child_node.splitWeight; } - } else { + } + else + { float n; if (TLeafEstimator == LeafEstimator::REJECTION_SAMPLING) n = 1.0f / ctx.stats->numSamples; @@ -260,8 +297,7 @@ class DirectionalQuadtreeFactory { if (TSplitMetric == SplitMetric::SECOND_MOMENT) node.splitWeight = std::sqrt(Sphere2Square::area(rect) * secondMoment); } - } - ); + }); // Build new tree according to split weights ctx.fitStats->numSplits = 0; @@ -273,7 +309,8 @@ class DirectionalQuadtreeFactory { ctx.fitStats->numNodes = ctx.stats->nodes.size(); ctx.dist->nodes.clear(); - for (auto &node : ctx.stats->nodes) { + for (auto &node : ctx.stats->nodes) + { DirectionalQuadtreeNode qnode; qnode.offsetChildren = node.offsetChildren; qnode.sampleWeight = node.sampleWeight; @@ -281,37 +318,49 @@ class DirectionalQuadtreeFactory { } } - void buildRecursive(Context &ctx, std::vector &old_nodes, Rect rect, uint32_t i, uint32_t j, uint32_t level = 0) { + void buildRecursive(Context &ctx, std::vector &old_nodes, Rect rect, uint32_t i, uint32_t j, uint32_t level = 0) + { StatsNode &old_node = old_nodes[i]; ctx.stats->nodes[j] = old_node; - if (level < ctx.cfg->maxLevels && old_node.splitWeight > (ctx.cfg->splitThreshold * old_nodes[0].splitWeight)) { + if (level < ctx.cfg->maxLevels && old_node.splitWeight > (ctx.cfg->splitThreshold * old_nodes[0].splitWeight)) + { ctx.stats->nodes[j].offsetChildren = ctx.stats->nodes.size(); - for (uint32_t c = 0; c < 4; c++) ctx.stats->nodes.emplace_back(); - if (old_node.offsetChildren > 0) { + for (uint32_t c = 0; c < 4; c++) + ctx.stats->nodes.emplace_back(); + if (old_node.offsetChildren > 0) + { for (uint32_t c = 0; c < 4; c++) buildRecursive(ctx, old_nodes, rect.child(c), old_node.offsetChildren + c, ctx.stats->nodes[j].offsetChildren + c, level + 1); } - else { + else + { // If we have encountered a leaf node that we want to split, // we continue with buildSplit to potentially further split the node ctx.fitStats->numSplits++; for (uint32_t c = 0; c < 4; c++) buildSplit(ctx, rect.child(c), j, ctx.stats->nodes[j].offsetChildren + c, level + 1); } - } else { + } + else + { ctx.stats->nodes[j].offsetChildren = 0; // continue traversal to quantify number of nodes that have been merged // TODO switch to disable this - traverse(old_nodes.data(), + traverse( + old_nodes.data(), [&](uint32_t i, Rect &rect) { - if (old_nodes[i].offsetChildren > 0) ctx.fitStats->numMerges++; + if (old_nodes[i].offsetChildren > 0) + ctx.fitStats->numMerges++; return true; }, - [&](uint32_t i, Rect &rect) { }, i, rect); + [&](uint32_t i, Rect &rect) { + }, + i, rect); } } - void buildSplit(Context &ctx, Rect rect, uint32_t p, uint32_t i, uint32_t level) { + void buildSplit(Context &ctx, Rect rect, uint32_t p, uint32_t i, uint32_t level) + { const auto &parent = ctx.stats->nodes[p]; auto &node = ctx.stats->nodes[i]; @@ -322,17 +371,19 @@ class DirectionalQuadtreeFactory { node.sampleWeight = parent.sampleWeight / 4; node.splitWeight = parent.splitWeight / 4; - return; // TODO splitting further seems to lead to overfitting + return; // TODO splitting further seems to lead to overfitting - if (level < ctx.cfg->maxLevels && node.splitWeight > (ctx.cfg->splitThreshold * ctx.stats->nodes[0].splitWeight)) { + if (level < ctx.cfg->maxLevels && node.splitWeight > (ctx.cfg->splitThreshold * ctx.stats->nodes[0].splitWeight)) + { ctx.fitStats->numSplits++; uint32_t offsetChildren = ctx.stats->nodes.size(); node.offsetChildren = offsetChildren; - for (uint32_t c = 0; c < 4; c++) ctx.stats->nodes.emplace_back(); + for (uint32_t c = 0; c < 4; c++) + ctx.stats->nodes.emplace_back(); for (uint32_t c = 0; c < 4; c++) buildSplit(ctx, rect.child(c), i, offsetChildren + c, level + 1); } } }; -} \ No newline at end of file +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/directional/dqt/DQTSurfaceSamplingDistribution.h b/openpgl/directional/dqt/DQTSurfaceSamplingDistribution.h index 91a1bf1..e4e8406 100644 --- a/openpgl/directional/dqt/DQTSurfaceSamplingDistribution.h +++ b/openpgl/directional/dqt/DQTSurfaceSamplingDistribution.h @@ -6,31 +6,36 @@ namespace openpgl { -template -struct DQTSurfaceSamplingDistribution: public ISurfaceSamplingDistribution { - DQTSurfaceSamplingDistribution() - {}; +template +struct DQTSurfaceSamplingDistribution : public ISurfaceSamplingDistribution +{ + DQTSurfaceSamplingDistribution(){}; - virtual ~DQTSurfaceSamplingDistribution() override {}; + virtual ~DQTSurfaceSamplingDistribution() override{}; - virtual void init(const void* distribution, Point3 samplePosition) override { - this->distribution = *(TDirectionalQuadtree*)distribution; + virtual void init(const void *distribution, Point3 samplePosition) override + { + this->distribution = *(TDirectionalQuadtree *)distribution; }; - inline void applyCosineProduct(const Vector3& normal) override { + inline void applyCosineProduct(const Vector3 &normal) override + { // not supported by quadtree return; }; - inline bool supportsApplyCosineProduct() const override { + inline bool supportsApplyCosineProduct() const override + { return false; } - inline Vector3 sample(const Point2 sample) const override { + inline Vector3 sample(const Point2 sample) const override + { return distribution.sample(sample); }; - inline float pdf(const Vector3 dir) const override { + inline float pdf(const Vector3 dir) const override + { return distribution.pdf(dir); }; @@ -39,7 +44,8 @@ struct DQTSurfaceSamplingDistribution: public ISurfaceSamplingDistribution { return distribution.samplePdf(sample, dir); } - inline float pdfLi(const Vector3 dir) const override { + inline float pdfLi(const Vector3 dir) const override + { return distribution.pdf(dir); }; #ifdef OPENPGL_RADIANCE_CACHES @@ -53,35 +59,37 @@ struct DQTSurfaceSamplingDistribution: public ISurfaceSamplingDistribution { return Vector3(0.f, 0.f, 0.f); } - inline Vector3 outgoingRadiance(const Vector3 dir) const override { return m_region->getOutgoingRadiance(dir); } #endif - inline bool validate() const override { + inline bool validate() const override + { return distribution.isValid(); }; - inline void clear() override { - }; + inline void clear() override {}; - std::string toString() const override { + std::string toString() const override + { return ""; }; - const IRegion* getRegion() const override { + const IRegion *getRegion() const override + { return m_region; } - void setRegion(const IRegion* region) override { + void setRegion(const IRegion *region) override + { m_region = region; } -private: + private: TDirectionalQuadtree distribution; - const IRegion* m_region {nullptr}; + const IRegion *m_region{nullptr}; }; -} \ No newline at end of file +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/directional/dqt/DQTVolumeSamplingDistribution.h b/openpgl/directional/dqt/DQTVolumeSamplingDistribution.h index 69fc409..8607b4f 100644 --- a/openpgl/directional/dqt/DQTVolumeSamplingDistribution.h +++ b/openpgl/directional/dqt/DQTVolumeSamplingDistribution.h @@ -6,30 +6,35 @@ namespace openpgl { -template -struct DQTVolumeSamplingDistribution: public IVolumeSamplingDistribution { - DQTVolumeSamplingDistribution() - {}; +template +struct DQTVolumeSamplingDistribution : public IVolumeSamplingDistribution +{ + DQTVolumeSamplingDistribution(){}; - virtual ~DQTVolumeSamplingDistribution() override {}; + virtual ~DQTVolumeSamplingDistribution() override{}; - virtual void init(const void* distribution, Point3 samplePosition) override { - this->distribution = *(TDirectionalQuadtree*)distribution; + virtual void init(const void *distribution, Point3 samplePosition) override + { + this->distribution = *(TDirectionalQuadtree *)distribution; }; - inline Vector3 sample(const Point2 sample) const override { + inline Vector3 sample(const Point2 sample) const override + { return distribution.sample(sample); }; - inline float pdf(const Vector3 dir) const override { + inline float pdf(const Vector3 dir) const override + { return distribution.pdf(dir); }; - inline float samplePdf(const Point2 sample, Vector3 &dir) const override { + inline float samplePdf(const Point2 sample, Vector3 &dir) const override + { return distribution.samplePdf(sample, dir); } - inline float pdfLi(const Vector3 dir) const override { + inline float pdfLi(const Vector3 dir) const override + { return distribution.pdf(dir); }; @@ -38,7 +43,7 @@ struct DQTVolumeSamplingDistribution: public IVolumeSamplingDistribution { { return Vector3(0.f, 0.f, 0.f); } - + inline Vector3 outgoingRadiance(const Vector3 dir) const override { return m_region->getOutgoingRadiance(dir); @@ -55,37 +60,42 @@ struct DQTVolumeSamplingDistribution: public IVolumeSamplingDistribution { } #endif - inline bool validate() const override { + inline bool validate() const override + { return distribution.isValid(); }; - inline void clear() override { - }; + inline void clear() override {}; - inline void applySingleLobeHenyeyGreensteinProduct(const Vector3& dir, const float meanCosine) override { + inline void applySingleLobeHenyeyGreensteinProduct(const Vector3 &dir, const float meanCosine) override + { // not supported by quadtree return; }; - inline bool supportsApplySingleLobeHenyeyGreensteinProduct() const override { + inline bool supportsApplySingleLobeHenyeyGreensteinProduct() const override + { return false; } - std::string toString() const override { + std::string toString() const override + { return ""; }; - const IRegion* getRegion() const override { + const IRegion *getRegion() const override + { return m_region; } - void setRegion(const IRegion* region) override { + void setRegion(const IRegion *region) override + { m_region = region; } -private: + private: TDirectionalQuadtree distribution; - const IRegion* m_region {nullptr}; + const IRegion *m_region{nullptr}; }; -} \ No newline at end of file +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/directional/dqt/Rect.h b/openpgl/directional/dqt/Rect.h index 4425154..2fbc44c 100644 --- a/openpgl/directional/dqt/Rect.h +++ b/openpgl/directional/dqt/Rect.h @@ -2,18 +2,22 @@ #include "../../openpgl_common.h" -namespace openpgl { +namespace openpgl +{ template -struct Rect { +struct Rect +{ embree::Vec2 min; embree::Vec2 max; - T area() { + T area() + { return (max.x - min.x) * (max.y - min.y); } - Rect intersect(const Rect &other) const { + Rect intersect(const Rect &other) const + { Rect isect; isect.min.x = std::max(min.x, other.min.x); isect.min.y = std::max(min.y, other.min.y); @@ -24,19 +28,11 @@ struct Rect { return isect; } - Rect child(uint32_t idx) const { + Rect child(uint32_t idx) const + { const embree::Vec2 mid = (min + max) / (T)2; - return { - { - (idx & 1) == 0 ? min.x : mid.x, - (idx & 2) == 0 ? min.y : mid.y - }, - { - (idx & 1) == 0 ? mid.x : max.x, - (idx & 2) == 0 ? mid.y : max.y - } - }; + return {{(idx & 1) == 0 ? min.x : mid.x, (idx & 2) == 0 ? min.y : mid.y}, {(idx & 1) == 0 ? mid.x : max.x, (idx & 2) == 0 ? mid.y : max.y}}; } }; -} \ No newline at end of file +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/directional/dqt/SphereToSquare.h b/openpgl/directional/dqt/SphereToSquare.h index 18b40e6..d7318c7 100644 --- a/openpgl/directional/dqt/SphereToSquare.h +++ b/openpgl/directional/dqt/SphereToSquare.h @@ -2,66 +2,69 @@ #include "../../openpgl_common.h" -namespace openpgl { - // We may remove this mapping at some point, because it has a singularity near z = 1 - class SphereToSquareLatLong { - public: - static Vector2 directionToPoint(const Vector3 &direction_) { - auto direction = embree::clamp(direction_, Vector3(-1), Vector3(1)); - float theta = std::acos(direction.z); - float phi = std::atan2(direction.y, direction.x); - return embree::clamp(Vector2(theta / M_PI_F, phi / (2 * M_PI_F) + 0.5), Vector2(0), Vector2(1)); - } +namespace openpgl +{ +// We may remove this mapping at some point, because it has a singularity near z = 1 +class SphereToSquareLatLong +{ + public: + static Vector2 directionToPoint(const Vector3 &direction_) + { + auto direction = embree::clamp(direction_, Vector3(-1), Vector3(1)); + float theta = std::acos(direction.z); + float phi = std::atan2(direction.y, direction.x); + return embree::clamp(Vector2(theta / M_PI_F, phi / (2 * M_PI_F) + 0.5), Vector2(0), Vector2(1)); + } - static Vector3 pointToDirection(const Vector2 &point_) { - auto point = embree::clamp(point_, Vector2(0), Vector2(1)); - float theta = point.x * M_PI_F; - float phi = (point.y - 0.5) * 2 * M_PI_F; - return embree::clamp(Vector3( - std::sin(theta) * std::cos(phi), - std::sin(theta) * std::sin(phi), - std::cos(theta) - ), Vector3(-1), Vector3(1)); - } + static Vector3 pointToDirection(const Vector2 &point_) + { + auto point = embree::clamp(point_, Vector2(0), Vector2(1)); + float theta = point.x * M_PI_F; + float phi = (point.y - 0.5) * 2 * M_PI_F; + return embree::clamp(Vector3(std::sin(theta) * std::cos(phi), std::sin(theta) * std::sin(phi), std::cos(theta)), Vector3(-1), Vector3(1)); + } - static float jacobian(const Vector2 &point_) { - auto point = embree::clamp(point_, Vector2(0), Vector2(1)); - float theta = point.x * M_PI_F; - return std::max(FLT_MIN, std::sin(theta) * 2.f * float(M_PI_F) * float(M_PI_F)); - } + static float jacobian(const Vector2 &point_) + { + auto point = embree::clamp(point_, Vector2(0), Vector2(1)); + float theta = point.x * M_PI_F; + return std::max(FLT_MIN, std::sin(theta) * 2.f * float(M_PI_F) * float(M_PI_F)); + } - static float area(const Rect& rect) { - return 2 * M_PI_F * (rect.max.y - rect.min.y) * (std::cos(M_PI_F * rect.min.x) - std::cos(M_PI_F * rect.max.x)); - } - }; + static float area(const Rect &rect) + { + return 2 * M_PI_F * (rect.max.y - rect.min.y) * (std::cos(M_PI_F * rect.min.x) - std::cos(M_PI_F * rect.max.x)); + } +}; - class SphereToSquareCylindrical { - public: - static Vector2 directionToPoint(const Vector3 &direction_) { - auto direction = embree::clamp(direction_, Vector3(-1), Vector3(1)); - float cosTheta = direction.z; - float phi = std::atan2(direction.y, direction.x); - return embree::clamp(Vector2((cosTheta + 1) / 2, phi / (2 * M_PI_F) + 0.5), Vector2(0), Vector2(1)); - } +class SphereToSquareCylindrical +{ + public: + static Vector2 directionToPoint(const Vector3 &direction_) + { + auto direction = embree::clamp(direction_, Vector3(-1), Vector3(1)); + float cosTheta = direction.z; + float phi = std::atan2(direction.y, direction.x); + return embree::clamp(Vector2((cosTheta + 1) / 2, phi / (2 * M_PI_F) + 0.5), Vector2(0), Vector2(1)); + } - static Vector3 pointToDirection(const Vector2 &point_) { - auto point = embree::clamp(point_, Vector2(0), Vector2(1)); - float cosTheta = 2 * point.x - 1; - float sinTheta = sqrt(1 - cosTheta * cosTheta); - float phi = (point.y - 0.5) * 2 * M_PI_F; - return embree::clamp(Vector3( - sinTheta * std::cos(phi), - sinTheta * std::sin(phi), - cosTheta - ), Vector3(-1), Vector3(1)); - } + static Vector3 pointToDirection(const Vector2 &point_) + { + auto point = embree::clamp(point_, Vector2(0), Vector2(1)); + float cosTheta = 2 * point.x - 1; + float sinTheta = sqrt(1 - cosTheta * cosTheta); + float phi = (point.y - 0.5) * 2 * M_PI_F; + return embree::clamp(Vector3(sinTheta * std::cos(phi), sinTheta * std::sin(phi), cosTheta), Vector3(-1), Vector3(1)); + } - static float jacobian(const Vector2 &point_) { - return 4.0f * M_PI_F; - } + static float jacobian(const Vector2 &point_) + { + return 4.0f * M_PI_F; + } - static float area(const Rect& rect) { - return 4.0f * M_PI_F * (rect.max.x - rect.min.x) * (rect.max.y - rect.min.y); - } - }; -} \ No newline at end of file + static float area(const Rect &rect) + { + return 4.0f * M_PI_F * (rect.max.x - rect.min.x) * (rect.max.y - rect.min.y); + } +}; +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/directional/dqt/Traversal.h b/openpgl/directional/dqt/Traversal.h index 9e4838e..fd708d8 100644 --- a/openpgl/directional/dqt/Traversal.h +++ b/openpgl/directional/dqt/Traversal.h @@ -2,33 +2,40 @@ #pragma once #include "../../openpgl_common.h" - #include "Rect.h" -namespace openpgl { +namespace openpgl +{ -inline bool rescale(float thresh, float &random) { +inline bool rescale(float thresh, float &random) +{ OPENPGL_ASSERT(0 <= thresh && thresh <= 1 && 0 <= random && random <= 1); - if (random < thresh) { + if (random < thresh) + { random /= thresh; return true; - } else { + } + else + { random -= thresh; random /= 1 - thresh; return false; } } -inline uint32_t rescaleChild(Vector2 &point) { +inline uint32_t rescaleChild(Vector2 &point) +{ OPENPGL_ASSERT(0.f <= point.x && point.x <= 1.f && 0.f <= point.y && point.y <= 1.f); uint32_t offset = 0; - if (point.x >= 0.5) { + if (point.x >= 0.5) + { point.x -= 0.5; offset += 1; } - if (point.y >= 0.5) { + if (point.y >= 0.5) + { point.y -= 0.5; offset += 2; } @@ -38,12 +45,14 @@ inline uint32_t rescaleChild(Vector2 &point) { // Generic query routine for quadtrees. // returns node and rectangle which a given point falls into -template -size_t queryNode(const TNode* nodes, Vector2 point, Rect &rect) { +template +size_t queryNode(const TNode *nodes, Vector2 point, Rect &rect) +{ rect = {{0, 0}, {1, 1}}; size_t nodeIdx = 0; - const TNode* node = &nodes[nodeIdx]; - while (node->offsetChildren > 0) { + const TNode *node = &nodes[nodeIdx]; + while (node->offsetChildren > 0) + { uint32_t c = rescaleChild(point); rect = rect.child(c); nodeIdx = node->offsetChildren + c; @@ -53,9 +62,11 @@ size_t queryNode(const TNode* nodes, Vector2 point, Rect &rect) { } // Generic traversal routine for quadtrees -template -void traverse(const TNode* nodes, F1 pre, F2 post, uint32_t i = 0, Rect rect = {{0, 0}, {1, 1}}) { - if (pre(i, rect) && nodes[i].offsetChildren > 0) { +template +void traverse(const TNode *nodes, F1 pre, F2 post, uint32_t i = 0, Rect rect = {{0, 0}, {1, 1}}) +{ + if (pre(i, rect) && nodes[i].offsetChildren > 0) + { for (uint32_t j = 0; j < 4; j++) traverse(nodes, pre, post, nodes[i].offsetChildren + j, rect.child(j)); } @@ -63,34 +74,38 @@ void traverse(const TNode* nodes, F1 pre, F2 post, uint32_t i = 0, Rect r } // Generic splatting routine for quadtrees -template -void splat(TNode* nodes, float footprintFactor, Vector2 point, F apply) { +template +void splat(TNode *nodes, float footprintFactor, Vector2 point, F apply) +{ Rect rect; size_t node_idx = queryNode(nodes, point, rect); - if (TIsFootprintFactorNonZero) { + if (TIsFootprintFactorNonZero) + { auto size = rect.max - rect.min; - Rect filterRect = { - point - footprintFactor * size / 2, - point + footprintFactor * size / 2 - }; + Rect filterRect = {point - footprintFactor * size / 2, point + footprintFactor * size / 2}; filterRect = filterRect.intersect({{0, 0}, {1, 1}}); float filterArea = filterRect.area(); OPENPGL_ASSERT(filterArea > 0); - traverse(nodes, + traverse( + nodes, [&](uint32_t i, Rect rect) { auto &node = nodes[i]; float nodeArea = filterRect.intersect(rect).area(); - if (nodeArea == 0) return false; - if (node.offsetChildren == 0) apply(node, nodeArea / filterArea); + if (nodeArea == 0) + return false; + if (node.offsetChildren == 0) + apply(node, nodeArea / filterArea); return true; }, - [&](uint32_t i, Rect rect) {} - ); - } else { + [&](uint32_t i, Rect rect) { + }); + } + else + { apply(nodes[node_idx], 1); } } -} \ No newline at end of file +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/directional/vmm/AdaptiveSplitandMergeFactory.h b/openpgl/directional/vmm/AdaptiveSplitandMergeFactory.h index ba261a7..aaabb1b 100644 --- a/openpgl/directional/vmm/AdaptiveSplitandMergeFactory.h +++ b/openpgl/directional/vmm/AdaptiveSplitandMergeFactory.h @@ -3,65 +3,62 @@ #pragma once -#include "../../openpgl_common.h" +#include +#include + #include "../../data/SampleData.h" #include "../../include/openpgl/types.h" - +#include "../../openpgl_common.h" #include "ParallaxAwareVonMisesFisherWeightedEMFactory.h" -#include "VMMChiSquareComponentSplitter.h" #include "VMMChiSquareComponentMerger.h" - -#include -#include +#include "VMMChiSquareComponentSplitter.h" namespace openpgl { -template +template struct AdaptiveSplitAndMergeFactory { - -public: - const static PGL_DIRECTIONAL_DISTRIBUTION_TYPE DIRECTIONAL_DISTRIBUTION_TYPE = TVMMDistribution::ParallaxCompensation ? PGL_DIRECTIONAL_DISTRIBUTION_PARALLAX_AWARE_VMM : PGL_DIRECTIONAL_DISTRIBUTION_VMM; + public: + const static PGL_DIRECTIONAL_DISTRIBUTION_TYPE DIRECTIONAL_DISTRIBUTION_TYPE = + TVMMDistribution::ParallaxCompensation ? PGL_DIRECTIONAL_DISTRIBUTION_PARALLAX_AWARE_VMM : PGL_DIRECTIONAL_DISTRIBUTION_VMM; typedef TVMMDistribution Distribution; typedef TVMMDistribution VMM; - //typedef WeightedEMVonMisesFisherFactory WeightedEMFactory; + // typedef WeightedEMVonMisesFisherFactory WeightedEMFactory; typedef ParallaxAwareVonMisesFisherWeightedEMFactory WeightedEMFactory; typedef VonMisesFisherChiSquareComponentSplitter Splitter; typedef VonMisesFisherChiSquareComponentMerger Merger; - struct Configuration { typename WeightedEMFactory::Configuration weightedEMCfg; - float splittingThreshold { 0.75f }; - float mergingThreshold { 0.00625f }; + float splittingThreshold{0.75f}; + float mergingThreshold{0.00625f}; - bool useSplitAndMerge {true}; + bool useSplitAndMerge{true}; - bool partialReFit { false }; - int maxSplitItr { 1 }; + bool partialReFit{false}; + int maxSplitItr{1}; - int minSamplesForSplitting { 0 }; - int minSamplesForPartialRefitting { 0 }; - int minSamplesForMerging { 0 }; + int minSamplesForSplitting{0}; + int minSamplesForPartialRefitting{0}; + int minSamplesForMerging{0}; - void serialize(std::ostream& stream) const; + void serialize(std::ostream &stream) const; - void deserialize(std::istream& stream); + void deserialize(std::istream &stream); std::string toString() const; - bool operator==(const Configuration& b) const { + bool operator==(const Configuration &b) const + { bool equal = true; - if(splittingThreshold != b.splittingThreshold || mergingThreshold != b.mergingThreshold || - useSplitAndMerge != b.useSplitAndMerge || partialReFit != b.partialReFit || - maxSplitItr != b.maxSplitItr || minSamplesForSplitting != b.minSamplesForSplitting || - minSamplesForPartialRefitting != b.minSamplesForPartialRefitting || minSamplesForMerging != b.minSamplesForMerging || - !weightedEMCfg.operator==(b.weightedEMCfg)) + if (splittingThreshold != b.splittingThreshold || mergingThreshold != b.mergingThreshold || useSplitAndMerge != b.useSplitAndMerge || partialReFit != b.partialReFit || + maxSplitItr != b.maxSplitItr || minSamplesForSplitting != b.minSamplesForSplitting || minSamplesForPartialRefitting != b.minSamplesForPartialRefitting || + minSamplesForMerging != b.minSamplesForMerging || !weightedEMCfg.operator==(b.weightedEMCfg)) { equal = false; } @@ -69,16 +66,15 @@ struct AdaptiveSplitAndMergeFactory } }; - struct Statistics { typename WeightedEMFactory::SufficientStatistics sufficientStatistics; typename Splitter::ComponentSplitStatistics splittingStatistics; - //size_t numComponents {0}; + // size_t numComponents {0}; - size_t numSamplesAfterLastSplit {0}; - size_t numSamplesAfterLastMerge {0}; + size_t numSamplesAfterLastSplit{0}; + size_t numSamplesAfterLastMerge{0}; Statistics() = default; @@ -87,9 +83,9 @@ struct AdaptiveSplitAndMergeFactory void decay(const float &alpha); - void serialize(std::ostream& stream) const; + void serialize(std::ostream &stream) const; - void deserialize(std::istream& stream); + void deserialize(std::istream &stream); bool isValid() const; @@ -101,33 +97,33 @@ struct AdaptiveSplitAndMergeFactory std::string toString() const; - bool operator==(const Statistics& b) const; - + bool operator==(const Statistics &b) const; }; struct FittingStatistics { - size_t numSamples {0}; - size_t numSplits {0}; - size_t numMerges {0}; + size_t numSamples{0}; + size_t numSplits{0}; + size_t numMerges{0}; - size_t numComponents {0}; + size_t numComponents{0}; - size_t numUpdateWEMIterations {0}; - size_t numPartialUpdateWEMIterations {0}; + size_t numUpdateWEMIterations{0}; + size_t numPartialUpdateWEMIterations{0}; std::string toString() const; }; - void prepareSamples(SampleData* samples, const size_t numSamples, const SampleStatistics &sampleStatistics, const Configuration &cfg) const; + void prepareSamples(SampleData *samples, const size_t numSamples, const SampleStatistics &sampleStatistics, const Configuration &cfg) const; - void fit(VMM &vmm, Statistics &stats, const SampleData* samples, const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) const; + void fit(VMM &vmm, Statistics &stats, const SampleData *samples, const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) const; - void update(VMM &vmm, Statistics &stats, const SampleData* samples, const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) const; + void update(VMM &vmm, Statistics &stats, const SampleData *samples, const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) const; - void updateFluenceEstimate(VMM &vmm, const SampleData* samples, const size_t numSamples, const size_t numZeroValueSamples, const SampleStatistics &sampleStatistics) const; + void updateFluenceEstimate(VMM &vmm, const SampleData *samples, const size_t numSamples, const size_t numZeroValueSamples, const SampleStatistics &sampleStatistics) const; - std::string toString() const{ + std::string toString() const + { std::ostringstream oss; WeightedEMFactory vmmFactory; oss << "AdaptiveSplitAndMergeFactory[\n"; @@ -136,40 +132,38 @@ struct AdaptiveSplitAndMergeFactory return oss.str(); } - }; -template -void AdaptiveSplitAndMergeFactory::Statistics::serialize(std::ostream& stream) const +template +void AdaptiveSplitAndMergeFactory::Statistics::serialize(std::ostream &stream) const { sufficientStatistics.serialize(stream); splittingStatistics.serialize(stream); - //stream.write(reinterpret_cast(&numComponents), sizeof(size_t)); - stream.write(reinterpret_cast(&numSamplesAfterLastSplit), sizeof(size_t)); - stream.write(reinterpret_cast(&numSamplesAfterLastMerge), sizeof(size_t)); + // stream.write(reinterpret_cast(&numComponents), sizeof(size_t)); + stream.write(reinterpret_cast(&numSamplesAfterLastSplit), sizeof(size_t)); + stream.write(reinterpret_cast(&numSamplesAfterLastMerge), sizeof(size_t)); } -template -void AdaptiveSplitAndMergeFactory::Statistics::deserialize(std::istream& stream) +template +void AdaptiveSplitAndMergeFactory::Statistics::deserialize(std::istream &stream) { sufficientStatistics.deserialize(stream); splittingStatistics.deserialize(stream); - //stream.read(reinterpret_cast(&numComponents), sizeof(size_t)); - stream.read(reinterpret_cast(&numSamplesAfterLastSplit), sizeof(size_t)); - stream.read(reinterpret_cast(&numSamplesAfterLastMerge), sizeof(size_t)); + // stream.read(reinterpret_cast(&numComponents), sizeof(size_t)); + stream.read(reinterpret_cast(&numSamplesAfterLastSplit), sizeof(size_t)); + stream.read(reinterpret_cast(&numSamplesAfterLastMerge), sizeof(size_t)); } -template +template void AdaptiveSplitAndMergeFactory::Statistics::decay(const float &alpha) { sufficientStatistics.decay(alpha); splittingStatistics.decay(alpha); } - -template +template bool AdaptiveSplitAndMergeFactory::Statistics::isValid() const { bool valid = true; @@ -185,7 +179,7 @@ bool AdaptiveSplitAndMergeFactory::Statistics::isValid() const return valid; } -template +template std::string AdaptiveSplitAndMergeFactory::Statistics::toString() const { std::stringstream ss; @@ -197,7 +191,7 @@ std::string AdaptiveSplitAndMergeFactory::Statistics::toString return ss.str(); } -template +template std::string AdaptiveSplitAndMergeFactory::FittingStatistics::toString() const { std::stringstream ss; @@ -211,72 +205,72 @@ std::string AdaptiveSplitAndMergeFactory::FittingStatistics::t return ss.str(); } -template +template void AdaptiveSplitAndMergeFactory::Statistics::clear(const size_t &_numComponents) { sufficientStatistics.clear(_numComponents); splittingStatistics.clear(_numComponents); - //numComponents = _numComponents; + // numComponents = _numComponents; numSamplesAfterLastSplit = 0; numSamplesAfterLastMerge = 0; } -template +template void AdaptiveSplitAndMergeFactory::Statistics::clearAll() { clear(VMM::MaxComponents); } -template -bool AdaptiveSplitAndMergeFactory::Statistics::operator==(const Statistics& b) const { +template +bool AdaptiveSplitAndMergeFactory::Statistics::operator==(const Statistics &b) const +{ bool equal = true; - if(numSamplesAfterLastSplit != b.numSamplesAfterLastSplit || numSamplesAfterLastMerge != b.numSamplesAfterLastMerge) + if (numSamplesAfterLastSplit != b.numSamplesAfterLastSplit || numSamplesAfterLastMerge != b.numSamplesAfterLastMerge) { equal = false; } - if(!sufficientStatistics.operator==(b.sufficientStatistics) || - !splittingStatistics.operator==(b.splittingStatistics)) + if (!sufficientStatistics.operator==(b.sufficientStatistics) || !splittingStatistics.operator==(b.splittingStatistics)) { equal = false; } return equal; } -template -void AdaptiveSplitAndMergeFactory::Configuration::serialize(std::ostream& stream) const +template +void AdaptiveSplitAndMergeFactory::Configuration::serialize(std::ostream &stream) const { weightedEMCfg.serialize(stream); - stream.write(reinterpret_cast(&splittingThreshold), sizeof(float)); - stream.write(reinterpret_cast(&mergingThreshold), sizeof(float)); + stream.write(reinterpret_cast(&splittingThreshold), sizeof(float)); + stream.write(reinterpret_cast(&mergingThreshold), sizeof(float)); - stream.write(reinterpret_cast(&partialReFit), sizeof(bool)); - stream.write(reinterpret_cast(&maxSplitItr), sizeof(int)); + stream.write(reinterpret_cast(&partialReFit), sizeof(bool)); + stream.write(reinterpret_cast(&maxSplitItr), sizeof(int)); - stream.write(reinterpret_cast(&minSamplesForSplitting), sizeof(int)); - stream.write(reinterpret_cast(&minSamplesForMerging), sizeof(int)); - stream.write(reinterpret_cast(&minSamplesForPartialRefitting), sizeof(int)); + stream.write(reinterpret_cast(&minSamplesForSplitting), sizeof(int)); + stream.write(reinterpret_cast(&minSamplesForMerging), sizeof(int)); + stream.write(reinterpret_cast(&minSamplesForPartialRefitting), sizeof(int)); } -template -void AdaptiveSplitAndMergeFactory::Configuration::deserialize(std::istream& stream) +template +void AdaptiveSplitAndMergeFactory::Configuration::deserialize(std::istream &stream) { weightedEMCfg.deserialize(stream); - stream.read(reinterpret_cast(&splittingThreshold), sizeof(float)); - stream.read(reinterpret_cast(&mergingThreshold), sizeof(float)); + stream.read(reinterpret_cast(&splittingThreshold), sizeof(float)); + stream.read(reinterpret_cast(&mergingThreshold), sizeof(float)); - stream.read(reinterpret_cast(&partialReFit), sizeof(bool)); - stream.read(reinterpret_cast(&maxSplitItr), sizeof(int)); + stream.read(reinterpret_cast(&partialReFit), sizeof(bool)); + stream.read(reinterpret_cast(&maxSplitItr), sizeof(int)); - stream.read(reinterpret_cast(&minSamplesForSplitting), sizeof(int)); - stream.read(reinterpret_cast(&minSamplesForMerging), sizeof(int)); - stream.read(reinterpret_cast(&minSamplesForPartialRefitting), sizeof(int)); + stream.read(reinterpret_cast(&minSamplesForSplitting), sizeof(int)); + stream.read(reinterpret_cast(&minSamplesForMerging), sizeof(int)); + stream.read(reinterpret_cast(&minSamplesForPartialRefitting), sizeof(int)); } -template +template std::string AdaptiveSplitAndMergeFactory::Configuration::toString() const { std::stringstream ss; @@ -293,16 +287,17 @@ std::string AdaptiveSplitAndMergeFactory::Configuration::toStr return ss.str(); } - -template -void AdaptiveSplitAndMergeFactory::prepareSamples(SampleData* samples, const size_t numSamples, const SampleStatistics &sampleStatistics, const Configuration &cfg) const +template +void AdaptiveSplitAndMergeFactory::prepareSamples(SampleData *samples, const size_t numSamples, const SampleStatistics &sampleStatistics, + const Configuration &cfg) const { WeightedEMFactory factory = WeightedEMFactory(); factory.prepareSamples(samples, numSamples, sampleStatistics, cfg.weightedEMCfg); } -template -void AdaptiveSplitAndMergeFactory::fit(VMM &vmm, Statistics &stats, const SampleData* samples, const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) const +template +void AdaptiveSplitAndMergeFactory::fit(VMM &vmm, Statistics &stats, const SampleData *samples, const size_t numSamples, const Configuration &cfg, + FittingStatistics &fitStats) const { const size_t numComponents = cfg.weightedEMCfg.initK; stats.clear(numComponents); @@ -314,19 +309,18 @@ void AdaptiveSplitAndMergeFactory::fit(VMM &vmm, Statistics &s OPENPGL_ASSERT(vmm.isValid()); OPENPGL_ASSERT(vmm.getNumComponents() == stats.sufficientStatistics.getNumComponents()); OPENPGL_ASSERT(stats.isValid()); -/* */ + /* */ if (cfg.useSplitAndMerge) { - // calculate the estimate of the integral of the function (e.g. radiance or importance) fitted by the VMM float mcEstimate = stats.sufficientStatistics.getSumWeights() / stats.sufficientStatistics.getNumSamples(); // split the fitted components of the inital fit to match // the observed samples - #ifdef OPENPGL_SHOW_PRINT_OUTS +#ifdef OPENPGL_SHOW_PRINT_OUTS std::cout << stats.sufficientStatistics.toString() << std::endl; - #endif +#endif Splitter splitter = Splitter(); splitter.PerformRecursiveSplitting(vmm, stats.sufficientStatistics, cfg.splittingThreshold, mcEstimate, samples, numSamples, cfg.weightedEMCfg); @@ -348,10 +342,9 @@ void AdaptiveSplitAndMergeFactory::fit(VMM &vmm, Statistics &s OPENPGL_ASSERT(vmm.isValid()); } - - -template -void AdaptiveSplitAndMergeFactory::update(VMM &vmm, Statistics &stats, const SampleData* samples, const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) const +template +void AdaptiveSplitAndMergeFactory::update(VMM &vmm, Statistics &stats, const SampleData *samples, const size_t numSamples, const Configuration &cfg, + FittingStatistics &fitStats) const { OPENPGL_ASSERT(vmm.isValid()); OPENPGL_ASSERT(vmm.getNumComponents() == stats.getNumComponents()); @@ -360,11 +353,11 @@ void AdaptiveSplitAndMergeFactory::update(VMM &vmm, Statistics // first update the mixture WeightedEMFactory factory = WeightedEMFactory(); typename WeightedEMFactory::FittingStatistics wemFitStats; - //stats.sufficientStatistics.clear(vmm._numComponents); + // stats.sufficientStatistics.clear(vmm._numComponents); const size_t prevNumberOfComponents = vmm._numComponents; factory.updateMixture(vmm, stats.sufficientStatistics, samples, numSamples, cfg.weightedEMCfg, wemFitStats); OPENPGL_ASSERT(vmm.isValid()); - // check if the update step added a new component. + // check if the update step added a new component. // This happnes if samples are not covered by any existing component // and we need to extend the splittingStats. if (prevNumberOfComponents < vmm._numComponents) @@ -375,7 +368,6 @@ void AdaptiveSplitAndMergeFactory::update(VMM &vmm, Statistics if (cfg.useSplitAndMerge) { - float mcEstimate = stats.sufficientStatistics.getSumWeights() / stats.sufficientStatistics.getNumSamples(); fitStats.numSamples = numSamples; @@ -385,7 +377,7 @@ void AdaptiveSplitAndMergeFactory::update(VMM &vmm, Statistics stats.numSamplesAfterLastMerge += numSamples; Splitter splitter = Splitter(); - //OPENPGL_ASSERT(stats.splittingStatistics.isValid()); + // OPENPGL_ASSERT(stats.splittingStatistics.isValid()); splitter.UpdateSplitStatistics(vmm, stats.splittingStatistics, mcEstimate, samples, numSamples); OPENPGL_ASSERT(stats.splittingStatistics.isValid()); @@ -396,15 +388,15 @@ void AdaptiveSplitAndMergeFactory::update(VMM &vmm, Statistics std::vector splitComps = stats.splittingStatistics.getSplitCandidates(); int totalSplitCount = 0; - //const size_t numComp = vmm._numComponents; + // const size_t numComp = vmm._numComponents; for (size_t k = 0; k < splitComps.size(); k++) { - if (splitComps[k].chiSquareEst > cfg.splittingThreshold && vmm._numComponents < VMM::MaxComponents) + if (splitComps[k].chiSquareEst > cfg.splittingThreshold && vmm._numComponents < VMM::MaxComponents) { splitter.SplitComponent(vmm, stats.splittingStatistics, stats.sufficientStatistics, splitComps[k].componentIndex); mask.setToTrue(splitComps[k].componentIndex); - mask.setToTrue(vmm._numComponents-1); - //std::cout << "split[" << totalSplitCount << "]: " << "\tidx0: " << splitComps[k].componentIndex << "\tidx1: " << vmm._numComponents-1 << std::endl; + mask.setToTrue(vmm._numComponents - 1); + // std::cout << "split[" << totalSplitCount << "]: " << "\tidx0: " << splitComps[k].componentIndex << "\tidx1: " << vmm._numComponents-1 << std::endl; totalSplitCount++; } } @@ -413,14 +405,14 @@ void AdaptiveSplitAndMergeFactory::update(VMM &vmm, Statistics OPENPGL_ASSERT(vmm.getNumComponents() == stats.getNumComponents()); OPENPGL_ASSERT(stats.isValid()); - if (totalSplitCount > 0 && cfg.partialReFit && numSamples >= cfg.minSamplesForPartialRefitting) + if (totalSplitCount > 0 && cfg.partialReFit && numSamples >= cfg.minSamplesForPartialRefitting) { typename WeightedEMFactory::SufficientStatistics tempSuffStatistics = stats.sufficientStatistics; tempSuffStatistics.clear(vmm._numComponents); factory.partialUpdateMixture(vmm, mask, tempSuffStatistics, samples, numSamples, cfg.weightedEMCfg, wemFitStats); stats.sufficientStatistics.setNumComponents(vmm._numComponents); stats.sufficientStatistics.maskedReplace(mask, tempSuffStatistics); - // update number of components for the splitStats to + // update number of components for the splitStats to // account for additionaly added componetes based on not covered samples. stats.splittingStatistics.setNumComponents(vmm._numComponents); fitStats.numPartialUpdateWEMIterations = wemFitStats.numIterations; @@ -433,7 +425,7 @@ void AdaptiveSplitAndMergeFactory::update(VMM &vmm, Statistics stats.numSamplesAfterLastSplit = 0.0f; #ifdef OPENPGL_SHOW_PRINT_OUTS - std::cout << "update: totalSplitCount = " << totalSplitCount << "\t splitThreshold: " << cfg.splittingThreshold<< std::endl; + std::cout << "update: totalSplitCount = " << totalSplitCount << "\t splitThreshold: " << cfg.splittingThreshold << std::endl; #endif } @@ -463,13 +455,12 @@ void AdaptiveSplitAndMergeFactory::update(VMM &vmm, Statistics OPENPGL_ASSERT(stats.sufficientStatistics.isValid()); } - -template -void AdaptiveSplitAndMergeFactory::updateFluenceEstimate(VMM &vmm, const SampleData* samples, const size_t numSamples, const size_t numZeroValueSamples, const SampleStatistics &sampleStatistics) const +template +void AdaptiveSplitAndMergeFactory::updateFluenceEstimate(VMM &vmm, const SampleData *samples, const size_t numSamples, const size_t numZeroValueSamples, + const SampleStatistics &sampleStatistics) const { WeightedEMFactory factory = WeightedEMFactory(); factory.updateFluenceEstimate(vmm, samples, numSamples, numZeroValueSamples, sampleStatistics); } -} - +} // namespace openpgl diff --git a/openpgl/directional/vmm/ParallaxAwareVonMisesFisherMixture.h b/openpgl/directional/vmm/ParallaxAwareVonMisesFisherMixture.h index 5d604bd..a00f949 100644 --- a/openpgl/directional/vmm/ParallaxAwareVonMisesFisherMixture.h +++ b/openpgl/directional/vmm/ParallaxAwareVonMisesFisherMixture.h @@ -3,53 +3,53 @@ #pragma once -#include "../../openpgl_common.h" - -#include - -#include -#include #include #include - +#include +#include +#include #include #include -#include - #include #include +#include + +#include "../../openpgl_common.h" #define OPENPGL_MIN_KAPPA 1e-3f #define USE_SIMD_CDF_SAMPLING -//#define VALIDATE_SELECT_COMPONENT_SIMD +// #define VALIDATE_SELECT_COMPONENT_SIMD namespace openpgl { -template +template Type MeanCosineToKappa(const Type &meanCosine); -template +template Type KappaToMeanCosine(const Type &kappa); -template +template struct ParallaxAwareVonMisesFisherMixture { - -public: - enum { + public: + enum + { ParallaxCompensation = UseParallaxCompensation }; - - enum{ + + enum + { MaxComponents = maxComponents, VectorSize = VecSize, - NumVectors = (maxComponents + (VecSize -1)) / VecSize + NumVectors = (maxComponents + (VecSize - 1)) / VecSize }; -public: - struct SoftAssignment{ + + public: + struct SoftAssignment + { embree::vfloat assignments[NumVectors]; size_t size; float pdf; @@ -57,14 +57,14 @@ struct ParallaxAwareVonMisesFisherMixture std::string toString() const; bool isValid() const; }; -public: + public: ParallaxAwareVonMisesFisherMixture() = default; // VMM attributes embree::vfloat _weights[NumVectors]; embree::vfloat _kappas[NumVectors]; - embree::Vec3 > _meanDirections[NumVectors]; + embree::Vec3> _meanDirections[NumVectors]; embree::vfloat _normalizations[NumVectors]; embree::vfloat _eMinus2Kappa[NumVectors]; @@ -74,46 +74,47 @@ struct ParallaxAwareVonMisesFisherMixture // Parallax-aware attributes embree::vfloat _distances[NumVectors]; - Point3 _pivotPosition {0.0f, 0.0f, 0.0f}; + Point3 _pivotPosition{0.0f, 0.0f, 0.0f}; #ifdef OPENPGL_RADIANCE_CACHES // fluence attributes - //float _fluence {0.0f}; - float _numFluenceSamples {0.f}; - Vector3 _fluenceRGB {0.0f, 0.0f, 0.0f}; - Vector3 _fluenceRGBWithMIS {0.0f, 0.0f, 0.0f}; - embree::Vec3 > _fluenceRGBWeightsWithMIS[NumVectors]; - embree::Vec3 > _fluenceRGBWeights[NumVectors]; + // float _fluence {0.0f}; + float _numFluenceSamples{0.f}; + Vector3 _fluenceRGB{0.0f, 0.0f, 0.0f}; + Vector3 _fluenceRGBWithMIS{0.0f, 0.0f, 0.0f}; + embree::Vec3> _fluenceRGBWeightsWithMIS[NumVectors]; + embree::Vec3> _fluenceRGBWeights[NumVectors]; #endif - void serialize(std::ostream& stream) const; + void serialize(std::ostream &stream) const; - void deserialize(std::istream& stream); + void deserialize(std::istream &stream); - void uniformInit( float kappa ); + void uniformInit(float kappa); - bool softAssignment( Vector3 direction, SoftAssignment &assignment ) const; + bool softAssignment(Vector3 direction, SoftAssignment &assignment) const; - float pdf( Vector3 direction ) const; + float pdf(Vector3 direction) const; - Vector3 sample( const Vector2 sample ) const; + Vector3 sample(const Vector2 sample) const; #ifdef USE_SIMD_CDF_SAMPLING - void selectComponentSIMD(uint32_t &selectedVector, uint32_t &selectedComponent, Vector2 &_sample) const; + void selectComponentSIMD(uint32_t &selectedVector, uint32_t &selectedComponent, Vector2 &_sample) const; #endif - void selectComponent(uint32_t &selectedVector, uint32_t &selectedComponent, Vector2 &_sample) const; + void selectComponent(uint32_t &selectedVector, uint32_t &selectedComponent, Vector2 &_sample) const; void mergeComponents(const size_t &idx0, const size_t &idx1); - void splitComponent(const size_t &idx0, const size_t &idx1, const float &weight0, const float &weight1, const Vector3 &meanDirection0, const Vector3 &meanDirection1, const float &meanCosine0, const float &meanCosine1); + void splitComponent(const size_t &idx0, const size_t &idx1, const float &weight0, const float &weight1, const Vector3 &meanDirection0, const Vector3 &meanDirection1, + const float &meanCosine0, const float &meanCosine1); - void performRelativeParallaxShift( const Vector3 &shiftDirection); + void performRelativeParallaxShift(const Vector3 &shiftDirection); #ifdef OPENPGL_RADIANCE_CACHES - Vector3 incomingRadiance( const Vector3 &direction, const bool directLightMIS) const; + Vector3 incomingRadiance(const Vector3 &direction, const bool directLightMIS) const; - Vector3 irradiance( const Vector3 &normal, const bool directLightMIS) const; + Vector3 irradiance(const Vector3 &normal, const bool directLightMIS) const; - Vector3 inscatteredRadiance( const Vector3 &dir, const float meanCosine, const bool directLightMIS) const; + Vector3 inscatteredRadiance(const Vector3 &dir, const float meanCosine, const bool directLightMIS) const; Vector3 fluence(const bool directLightMIS) const; #endif @@ -168,32 +169,32 @@ struct ParallaxAwareVonMisesFisherMixture void _normalizeWeights(); - bool operator==(const ParallaxAwareVonMisesFisherMixture& b) const; - -private: - embree::vfloat _convolvePDF(const size_t k, const embree::Vec3< embree::vfloat >& normal, const embree::vfloat& meanCosine) const; + bool operator==(const ParallaxAwareVonMisesFisherMixture &b) const; + private: + embree::vfloat _convolvePDF(const size_t k, const embree::Vec3> &normal, const embree::vfloat &meanCosine) const; }; -template -size_t ParallaxAwareVonMisesFisherMixture::getNumComponents() const +template +size_t ParallaxAwareVonMisesFisherMixture::getNumComponents() const { return _numComponents; } -template -void ParallaxAwareVonMisesFisherMixture::setNumComponents(const size_t &numComponents) +template +void ParallaxAwareVonMisesFisherMixture::setNumComponents(const size_t &numComponents) { _numComponents = numComponents; } -template -std::string ParallaxAwareVonMisesFisherMixture::SoftAssignment::toString() const{ +template +std::string ParallaxAwareVonMisesFisherMixture::SoftAssignment::toString() const +{ std::stringstream ss; ss << "SoftAssignment:" << std::endl; ss << "size: " << size << std::endl; ss << "pdf: " << pdf << std::endl; - for ( int k = 0; k < size; k++) + for (int k = 0; k < size; k++) { const div_t tmp = div(k, static_cast(VecSize)); ss << "assign[" << k << "]: " << assignments[tmp.quot][tmp.rem]; @@ -202,19 +203,20 @@ std::string ParallaxAwareVonMisesFisherMixture -bool ParallaxAwareVonMisesFisherMixture::SoftAssignment::isValid() const{ +template +bool ParallaxAwareVonMisesFisherMixture::SoftAssignment::isValid() const +{ bool valid = true; valid = valid && size > 0; valid = valid && size <= maxComponents; OPENPGL_ASSERT(valid); - valid = valid && pdf >= 0; + valid = valid && pdf >= 0; valid = valid && embree::isvalid(pdf); OPENPGL_ASSERT(valid); - for ( int k = 0; k < size; k++) + for (int k = 0; k < size; k++) { const div_t tmpK = div(k, static_cast(VecSize)); valid = valid && assignments[tmpK.quot][tmpK.rem] >= 0.0f; @@ -225,35 +227,40 @@ bool ParallaxAwareVonMisesFisherMixture -std::string ParallaxAwareVonMisesFisherMixture::toString() const{ +template +std::string ParallaxAwareVonMisesFisherMixture::toString() const +{ std::stringstream ss; ss.precision(5); - if(UseParallaxCompensation) + if (UseParallaxCompensation) ss << "ParallaxAwareVonMisesFisherMixture:" << std::endl; else ss << "VonMisesFisherMixture:" << std::endl; ss << "maxComponents: " << maxComponents << std::endl; ss << "VecSize: " << VecSize << std::endl; ss << "numVectors: " << NumVectors << std::endl; - ss << "---------------------- " << std::endl; + ss << "---------------------- " << std::endl; ss << "numComponents: " << this->_numComponents << std::endl; float sumWeights = 0.0f; - //for ( int k = 0; k < this->_numComponents; k++) - for ( int k = 0; k < maxComponents; k++) + // for ( int k = 0; k < this->_numComponents; k++) + for (int k = 0; k < maxComponents; k++) { const div_t tmp = div(k, static_cast(VecSize)); ss << "vmm[" << k << "]: " << "weight: " << this->_weights[tmp.quot][tmp.rem]; - ss << "\t kappa: " << this->_kappas[tmp.quot][tmp.rem]; - ss << "\t meanDirection: [" << this->_meanDirections[tmp.quot].x[tmp.rem] << "\t" << this->_meanDirections[tmp.quot].y[tmp.rem] << "\t" << this->_meanDirections[tmp.quot].z[tmp.rem] << "]"; - ss << "\t length: " << embree::length(Vector3(this->_meanDirections[tmp.quot].x[tmp.rem], this->_meanDirections[tmp.quot].y[tmp.rem], this->_meanDirections[tmp.quot].z[tmp.rem])); - ss << "\t normalization: " << this->_normalizations[tmp.quot][tmp.rem]; - ss << "\t eMinus2Kappa: " << this->_eMinus2Kappa[tmp.quot][tmp.rem]; - ss << "\t meanCosine: " << this->_meanCosines[tmp.quot][tmp.rem]; - ss << "\t distance: " << _distances[tmp.quot][tmp.rem]; + ss << "\t kappa: " << this->_kappas[tmp.quot][tmp.rem]; + ss << "\t meanDirection: [" << this->_meanDirections[tmp.quot].x[tmp.rem] << "\t" << this->_meanDirections[tmp.quot].y[tmp.rem] << "\t" + << this->_meanDirections[tmp.quot].z[tmp.rem] << "]"; + ss << "\t length: " + << embree::length(Vector3(this->_meanDirections[tmp.quot].x[tmp.rem], this->_meanDirections[tmp.quot].y[tmp.rem], this->_meanDirections[tmp.quot].z[tmp.rem])); + ss << "\t normalization: " << this->_normalizations[tmp.quot][tmp.rem]; + ss << "\t eMinus2Kappa: " << this->_eMinus2Kappa[tmp.quot][tmp.rem]; + ss << "\t meanCosine: " << this->_meanCosines[tmp.quot][tmp.rem]; + ss << "\t distance: " << _distances[tmp.quot][tmp.rem]; #ifdef OPENPGL_RADIANCE_CACHES - ss << "\t fluenceRGBWeightWithMIS: " << _fluenceRGBWeightsWithMIS[tmp.quot].x[tmp.rem] << "\t" << _fluenceRGBWeightsWithMIS[tmp.quot].y[tmp.rem] << "\t" << _fluenceRGBWeightsWithMIS[tmp.quot].z[tmp.rem]; - ss << "\t fluenceRGBWeight: " << _fluenceRGBWeights[tmp.quot].x[tmp.rem] << "\t" << _fluenceRGBWeights[tmp.quot].y[tmp.rem] << "\t" << _fluenceRGBWeights[tmp.quot].z[tmp.rem]; + ss << "\t fluenceRGBWeightWithMIS: " << _fluenceRGBWeightsWithMIS[tmp.quot].x[tmp.rem] << "\t" << _fluenceRGBWeightsWithMIS[tmp.quot].y[tmp.rem] << "\t" + << _fluenceRGBWeightsWithMIS[tmp.quot].z[tmp.rem]; + ss << "\t fluenceRGBWeight: " << _fluenceRGBWeights[tmp.quot].x[tmp.rem] << "\t" << _fluenceRGBWeights[tmp.quot].y[tmp.rem] << "\t" + << _fluenceRGBWeights[tmp.quot].z[tmp.rem]; #endif ss << std::endl; sumWeights += this->_weights[tmp.quot][tmp.rem]; @@ -262,7 +269,7 @@ std::string ParallaxAwareVonMisesFisherMixture -void ParallaxAwareVonMisesFisherMixture::splitComponent(const size_t &idx0, const size_t &idx1, const float &weight0, const float &weight1, const Vector3 &meanDirection0, const Vector3 &meanDirection1, const float &meanCosine0, const float &meanCosine1) +template +void ParallaxAwareVonMisesFisherMixture::splitComponent(const size_t &idx0, const size_t &idx1, const float &weight0, + const float &weight1, const Vector3 &meanDirection0, + const Vector3 &meanDirection1, const float &meanCosine0, + const float &meanCosine1) { - OPENPGL_ASSERT(meanCosine0 > 0.0f && meanCosine0 <=1.0f); - OPENPGL_ASSERT(meanCosine1 > 0.0f && meanCosine1 <=1.0f); + OPENPGL_ASSERT(meanCosine0 > 0.0f && meanCosine0 <= 1.0f); + OPENPGL_ASSERT(meanCosine1 > 0.0f && meanCosine1 <= 1.0f); const div_t tmpIdx0 = div(idx0, static_cast(VectorSize)); const div_t tmpIdx1 = div(idx1, static_cast(VectorSize)); @@ -282,14 +292,14 @@ void ParallaxAwareVonMisesFisherMixture (meanCosine0); + _kappas[tmpIdx0.quot][tmpIdx0.rem] = MeanCosineToKappa(meanCosine0); _meanDirections[tmpIdx0.quot].x[tmpIdx0.rem] = meanDirection0.x; _meanDirections[tmpIdx0.quot].y[tmpIdx0.rem] = meanDirection0.y; _meanDirections[tmpIdx0.quot].z[tmpIdx0.rem] = meanDirection0.z; _weights[tmpIdx1.quot][tmpIdx1.rem] = weight1; _meanCosines[tmpIdx1.quot][tmpIdx1.rem] = meanCosine1; - _kappas[tmpIdx1.quot][tmpIdx1.rem] = MeanCosineToKappa (meanCosine1); + _kappas[tmpIdx1.quot][tmpIdx1.rem] = MeanCosineToKappa(meanCosine1); _meanDirections[tmpIdx1.quot].x[tmpIdx1.rem] = meanDirection1.x; _meanDirections[tmpIdx1.quot].y[tmpIdx1.rem] = meanDirection1.y; _meanDirections[tmpIdx1.quot].z[tmpIdx1.rem] = meanDirection1.z; @@ -316,20 +326,20 @@ void ParallaxAwareVonMisesFisherMixture -void ParallaxAwareVonMisesFisherMixture::mergeComponents(const size_t &idx0, const size_t &idx1) +template +void ParallaxAwareVonMisesFisherMixture::mergeComponents(const size_t &idx0, const size_t &idx1) { - const div_t tmpIdx0 = div( idx0, VecSize); - const div_t tmpIdx1 = div( idx1, VecSize); + const div_t tmpIdx0 = div(idx0, VecSize); + const div_t tmpIdx1 = div(idx1, VecSize); - //const div_t tmpIdx2 = div( this->_numComponents -1, VecSize); + // const div_t tmpIdx2 = div( this->_numComponents -1, VecSize); if (idx0 != idx1) { const float weight0 = _weights[tmpIdx0.quot][tmpIdx0.rem]; @@ -338,41 +348,35 @@ void ParallaxAwareVonMisesFisherMixture 0.0f ) + if (meanCosine > 0.0f) { meanCosine = std::sqrt(meanCosine); kappa = MeanCosineToKappa(meanCosine); kappa = kappa < 1e-3f ? 0.f : kappa; - //eMin2Kappa = math::fastexp( -2.0f * kappa ); - eMin2Kappa = embree::exp( -2.0f * kappa ); - norm = kappa / ( 2.0f * M_PI_F * ( 1.0f - eMin2Kappa ) ); + // eMin2Kappa = math::fastexp( -2.0f * kappa ); + eMin2Kappa = embree::exp(-2.0f * kappa); + norm = kappa / (2.0f * M_PI_F * (1.0f - eMin2Kappa)); meanDirectionX /= meanCosine; meanDirectionY /= meanCosine; @@ -404,30 +408,35 @@ void ParallaxAwareVonMisesFisherMixture -void ParallaxAwareVonMisesFisherMixture::swapComponents( const size_t &idx0, const size_t &idx1 ) +template +void ParallaxAwareVonMisesFisherMixture::swapComponents(const size_t &idx0, const size_t &idx1) { - const div_t tmpIdx0 = div( idx0, VecSize); - const div_t tmpIdx1 = div( idx1, VecSize); + const div_t tmpIdx0 = div(idx0, VecSize); + const div_t tmpIdx1 = div(idx1, VecSize); if (idx0 != idx1) { @@ -454,12 +463,12 @@ void ParallaxAwareVonMisesFisherMixture -void ParallaxAwareVonMisesFisherMixture::clearComponent( const size_t &idx ) +template +void ParallaxAwareVonMisesFisherMixture::clearComponent(const size_t &idx) { - const div_t tmpIdx = div( idx, VecSize); + const div_t tmpIdx = div(idx, VecSize); - _weights[tmpIdx.quot][tmpIdx.rem]= 0.f; + _weights[tmpIdx.quot][tmpIdx.rem] = 0.f; _kappas[tmpIdx.quot][tmpIdx.rem] = 0.f; _eMinus2Kappa[tmpIdx.quot][tmpIdx.rem] = 1.f; _meanCosines[tmpIdx.quot][tmpIdx.rem] = 0.f; @@ -482,8 +491,8 @@ void ParallaxAwareVonMisesFisherMixture -void ParallaxAwareVonMisesFisherMixture::serialize(std::ostream& stream) const +template +void ParallaxAwareVonMisesFisherMixture::serialize(std::ostream &stream) const { serializeFloatVectors(stream, _weights); serializeFloatVectors(stream, _kappas); @@ -493,22 +502,22 @@ void ParallaxAwareVonMisesFisherMixture(stream, _meanCosines); serializeFloatVectors(stream, _distances); #ifdef OPENPGL_RADIANCE_CACHES - serializeVec3Vectors(stream, _fluenceRGBWeightsWithMIS); + serializeVec3Vectors(stream, _fluenceRGBWeightsWithMIS); serializeVec3Vectors(stream, _fluenceRGBWeights); #endif - stream.write(reinterpret_cast(&_numComponents), sizeof(_numComponents)); - stream.write(reinterpret_cast(&_pivotPosition), sizeof(Point3)); + stream.write(reinterpret_cast(&_numComponents), sizeof(_numComponents)); + stream.write(reinterpret_cast(&_pivotPosition), sizeof(Point3)); #ifdef OPENPGL_RADIANCE_CACHES - //stream.write(reinterpret_cast(&_fluence), sizeof(float)); - stream.write(reinterpret_cast(&_fluenceRGB), sizeof(Vector3)); - stream.write(reinterpret_cast(&_fluenceRGBWithMIS), sizeof(Vector3)); - stream.write(reinterpret_cast(&_numFluenceSamples), sizeof(float)); + // stream.write(reinterpret_cast(&_fluence), sizeof(float)); + stream.write(reinterpret_cast(&_fluenceRGB), sizeof(Vector3)); + stream.write(reinterpret_cast(&_fluenceRGBWithMIS), sizeof(Vector3)); + stream.write(reinterpret_cast(&_numFluenceSamples), sizeof(float)); #endif } -template -void ParallaxAwareVonMisesFisherMixture::deserialize(std::istream& stream) +template +void ParallaxAwareVonMisesFisherMixture::deserialize(std::istream &stream) { deserializeFloatVectors(stream, _weights); deserializeFloatVectors(stream, _kappas); @@ -518,28 +527,29 @@ void ParallaxAwareVonMisesFisherMixture(stream, _meanCosines); deserializeFloatVectors(stream, _distances); #ifdef OPENPGL_RADIANCE_CACHES - deserializeVec3Vectors(stream, _fluenceRGBWeightsWithMIS); + deserializeVec3Vectors(stream, _fluenceRGBWeightsWithMIS); deserializeVec3Vectors(stream, _fluenceRGBWeights); #endif - stream.read(reinterpret_cast(&_numComponents), sizeof(_numComponents)); - stream.read(reinterpret_cast(&_pivotPosition), sizeof(Point3)); + stream.read(reinterpret_cast(&_numComponents), sizeof(_numComponents)); + stream.read(reinterpret_cast(&_pivotPosition), sizeof(Point3)); #ifdef OPENPGL_RADIANCE_CACHES - //stream.read(reinterpret_cast(&_fluence), sizeof(float)); - stream.read(reinterpret_cast(&_fluenceRGB), sizeof(Vector3)); - stream.read(reinterpret_cast(&_fluenceRGBWithMIS), sizeof(Vector3)); - stream.read(reinterpret_cast(&_numFluenceSamples), sizeof(float)); + // stream.read(reinterpret_cast(&_fluence), sizeof(float)); + stream.read(reinterpret_cast(&_fluenceRGB), sizeof(Vector3)); + stream.read(reinterpret_cast(&_fluenceRGBWithMIS), sizeof(Vector3)); + stream.read(reinterpret_cast(&_numFluenceSamples), sizeof(float)); #endif } -template -bool ParallaxAwareVonMisesFisherMixture::isValid() const +template +bool ParallaxAwareVonMisesFisherMixture::isValid() const { - bool valid = true; + bool valid = true; float sumWeights = 0.0f; - for(size_t k = 0; k < _numComponents; k++){ - const div_t tmpK = div( k, VecSize ); + for (size_t k = 0; k < _numComponents; k++) + { + const div_t tmpK = div(k, VecSize); sumWeights += _weights[tmpK.quot][tmpK.rem]; valid = valid && embree::isvalid(_weights[tmpK.quot][tmpK.rem]); @@ -584,8 +594,9 @@ bool ParallaxAwareVonMisesFisherMixture -void ParallaxAwareVonMisesFisherMixture::setComponentWeight(const size_t idx, const float &weight) +template +void ParallaxAwareVonMisesFisherMixture::setComponentWeight(const size_t idx, const float &weight) { - const div_t tmpIdx = div( idx, VecSize); + const div_t tmpIdx = div(idx, VecSize); - _weights[tmpIdx.quot][tmpIdx.rem]= weight; + _weights[tmpIdx.quot][tmpIdx.rem] = weight; } -template -void ParallaxAwareVonMisesFisherMixture::setComponentKappa(const size_t idx, const float &kappa) +template +void ParallaxAwareVonMisesFisherMixture::setComponentKappa(const size_t idx, const float &kappa) { - const div_t tmpIdx = div( idx, VecSize); + const div_t tmpIdx = div(idx, VecSize); - _kappas[tmpIdx.quot][tmpIdx.rem]= kappa; + _kappas[tmpIdx.quot][tmpIdx.rem] = kappa; _calculateNormalization(); _calculateMeanCosines(); } -template -void ParallaxAwareVonMisesFisherMixture::setComponentMeanDirection(const size_t idx, const Vector3 &meanDirection) +template +void ParallaxAwareVonMisesFisherMixture::setComponentMeanDirection(const size_t idx, const Vector3 &meanDirection) { - const div_t tmpIdx = div( idx, VecSize); + const div_t tmpIdx = div(idx, VecSize); _meanDirections[tmpIdx.quot].x[tmpIdx.rem] = meanDirection.x; _meanDirections[tmpIdx.quot].y[tmpIdx.rem] = meanDirection.y; _meanDirections[tmpIdx.quot].z[tmpIdx.rem] = meanDirection.z; } -template -Vector3 ParallaxAwareVonMisesFisherMixture::getComponentMeanDirection(const size_t &idx) const +template +Vector3 ParallaxAwareVonMisesFisherMixture::getComponentMeanDirection(const size_t &idx) const { - const div_t tmpIdx = div( idx, VecSize); - return Vector3( _meanDirections[tmpIdx.quot].x[tmpIdx.rem], _meanDirections[tmpIdx.quot].y[tmpIdx.rem], _meanDirections[tmpIdx.quot].z[tmpIdx.rem]); + const div_t tmpIdx = div(idx, VecSize); + return Vector3(_meanDirections[tmpIdx.quot].x[tmpIdx.rem], _meanDirections[tmpIdx.quot].y[tmpIdx.rem], _meanDirections[tmpIdx.quot].z[tmpIdx.rem]); } -template -float ParallaxAwareVonMisesFisherMixture::getComponentWeight(const size_t &idx) const +template +float ParallaxAwareVonMisesFisherMixture::getComponentWeight(const size_t &idx) const { - const div_t tmpIdx = div( idx, VecSize); + const div_t tmpIdx = div(idx, VecSize); return _weights[tmpIdx.quot][tmpIdx.rem]; } -template -float ParallaxAwareVonMisesFisherMixture::getComponentKappa(const size_t &idx) const +template +float ParallaxAwareVonMisesFisherMixture::getComponentKappa(const size_t &idx) const { - const div_t tmpIdx = div( idx, VecSize); + const div_t tmpIdx = div(idx, VecSize); return _kappas[tmpIdx.quot][tmpIdx.rem]; } -template -void ParallaxAwareVonMisesFisherMixture::setComponentDistance(const size_t &idx, const float &distance) +template +void ParallaxAwareVonMisesFisherMixture::setComponentDistance(const size_t &idx, const float &distance) { - const div_t tmpIdx = div( idx, VecSize); - _distances[tmpIdx.quot][tmpIdx.rem]= distance; + const div_t tmpIdx = div(idx, VecSize); + _distances[tmpIdx.quot][tmpIdx.rem] = distance; } -template -float ParallaxAwareVonMisesFisherMixture::getComponentDistance(const size_t &idx) const +template +float ParallaxAwareVonMisesFisherMixture::getComponentDistance(const size_t &idx) const { - const div_t tmpIdx = div( idx, VecSize); + const div_t tmpIdx = div(idx, VecSize); return _distances[tmpIdx.quot][tmpIdx.rem]; } -template -void ParallaxAwareVonMisesFisherMixture::convole(const float &_meanCosine) +template +void ParallaxAwareVonMisesFisherMixture::convole(const float &_meanCosine) { - const int cnt = (_numComponents+VecSize-1) / VecSize; + const int cnt = (_numComponents + VecSize - 1) / VecSize; const embree::vfloat meanCosine = _meanCosine; - for(int k = 0; k < cnt;k++) + for (int k = 0; k < cnt; k++) { _meanCosines[k] *= meanCosine; - _kappas[k] = MeanCosineToKappa< embree::vfloat >(meanCosine); + _kappas[k] = MeanCosineToKappa>(meanCosine); } _calculateNormalization(); } -template -float ParallaxAwareVonMisesFisherMixture::product(const float &_weight, const Vector3 &_meanDirection, const float &_kappa) +template +float ParallaxAwareVonMisesFisherMixture::product(const float &_weight, const Vector3 &_meanDirection, const float &_kappa) { - float _normalization = ONE_OVER_FOUR_PI; - //float _eMinus2Kappa = embree::fastapprox::exp< float >(-2.0f * _kappa); - // TODO: use faster exp + // float _eMinus2Kappa = embree::fastapprox::exp< float >(-2.0f * _kappa); + // TODO: use faster exp float _eMinus2Kappa = std::exp(-2.0f * _kappa); - if ( _kappa > 0.0f) + if (_kappa > 0.0f) { - _normalization = _kappa/(2.0f*M_PI_F*(1.0f-_eMinus2Kappa)); + _normalization = _kappa / (2.0f * M_PI_F * (1.0f - _eMinus2Kappa)); } return this->product(_weight, _meanDirection, _kappa, _normalization); } -template -float ParallaxAwareVonMisesFisherMixture::product(const float &_weight, const Vector3 &_meanDirection, const float &_kappa, const float &_normalization) +template +float ParallaxAwareVonMisesFisherMixture::product(const float &_weight, const Vector3 &_meanDirection, const float &_kappa, + const float &_normalization) { - const embree::vfloat twoPi(2.0f*M_PI_F); + const embree::vfloat twoPi(2.0f * M_PI_F); const embree::vfloat ones(1.0f); const embree::vfloat minusTwos(-2.0f); const embree::vfloat zeros(0.0f); const embree::vfloat zeroKappaNorm(ONE_OVER_FOUR_PI); - const int cnt = (_numComponents+VecSize-1) / VecSize; + const int cnt = (_numComponents + VecSize - 1) / VecSize; const int rem = _numComponents % VecSize; const embree::vfloat weight = _weight; const embree::vfloat kappa = _kappa; const embree::vfloat normalization = _normalization; - const embree::Vec3 > meanDirection = _meanDirection; + const embree::Vec3> meanDirection = _meanDirection; embree::vfloat productIntegralVec(0.f); - for(int k = 0; k < cnt;k++) + for (int k = 0; k < cnt; k++) { - embree::Vec3 > newMeanDirection = _kappas[k] * _meanDirections[k] + kappa * meanDirection; - embree::vfloat newKappa = embree::sqrt(embree::dot( newMeanDirection, newMeanDirection)); + embree::Vec3> newMeanDirection = _kappas[k] * _meanDirections[k] + kappa * meanDirection; + embree::vfloat newKappa = embree::sqrt(embree::dot(newMeanDirection, newMeanDirection)); auto checkNewKappa = (newKappa > 1e-3f); - newKappa = select( checkNewKappa, newKappa, zeros); + newKappa = select(checkNewKappa, newKappa, zeros); // TODO: update meanCosine - newMeanDirection.x = select( checkNewKappa, newMeanDirection.x / newKappa, _meanDirections[k].x); - newMeanDirection.y = select( checkNewKappa, newMeanDirection.y / newKappa, _meanDirections[k].y); - newMeanDirection.z = select( checkNewKappa, newMeanDirection.z / newKappa, _meanDirections[k].z); + newMeanDirection.x = select(checkNewKappa, newMeanDirection.x / newKappa, _meanDirections[k].x); + newMeanDirection.y = select(checkNewKappa, newMeanDirection.y / newKappa, _meanDirections[k].y); + newMeanDirection.z = select(checkNewKappa, newMeanDirection.z / newKappa, _meanDirections[k].z); embree::vfloat newEMinus2Kappa = embree::fastapprox::exp(minusTwos * newKappa); - embree::vfloat newNormalization = newKappa / (twoPi * ( ones - newEMinus2Kappa )); - newNormalization = select( checkNewKappa, newNormalization, zeroKappaNorm); + embree::vfloat newNormalization = newKappa / (twoPi * (ones - newEMinus2Kappa)); + newNormalization = select(checkNewKappa, newNormalization, zeroKappaNorm); - embree::vfloat scale = ( _normalizations[k] * normalization ) / newNormalization; + embree::vfloat scale = (_normalizations[k] * normalization) / newNormalization; - embree::vfloat cosTheta0 = embree::dot( _meanDirections[k], newMeanDirection ); - embree::vfloat cosTheta1 = embree::dot( meanDirection, newMeanDirection ); + embree::vfloat cosTheta0 = embree::dot(_meanDirections[k], newMeanDirection); + embree::vfloat cosTheta1 = embree::dot(meanDirection, newMeanDirection); - //std::cout << "cosTheta0: " << cosTheta0 <<"\tcosTheta1: " << cosTheta1 << std::endl; - //std::cout << "_kappas[k]: " << _kappas[k] <<"\tkappa: " << kappa << std::endl; - //std::cout << "tmp: " << _kappas[k] * (cosTheta0 - ones) + kappa * (cosTheta1 - ones) << std::endl; - embree::vfloat eval = embree::fastapprox::exp( _kappas[k] * (cosTheta0 - ones) + kappa * (cosTheta1 - ones) ); - //std::cout << "scale: " << scale <<"\teval: " << eval << std::endl; + // std::cout << "cosTheta0: " << cosTheta0 <<"\tcosTheta1: " << cosTheta1 << std::endl; + // std::cout << "_kappas[k]: " << _kappas[k] <<"\tkappa: " << kappa << std::endl; + // std::cout << "tmp: " << _kappas[k] * (cosTheta0 - ones) + kappa * (cosTheta1 - ones) << std::endl; + embree::vfloat eval = embree::fastapprox::exp(_kappas[k] * (cosTheta0 - ones) + kappa * (cosTheta1 - ones)); + // std::cout << "scale: " << scale <<"\teval: " << eval << std::endl; scale *= eval; scale *= _weights[k] * weight; @@ -778,24 +789,24 @@ float ParallaxAwareVonMisesFisherMixture 0 ) + if (rem > 0) { - for ( size_t i = rem; i < VecSize; i++) + for (size_t i = rem; i < VecSize; i++) { - _meanDirections[cnt-1].x[i] = 0.0f; - _meanDirections[cnt-1].y[i] = 0.0f; - _meanDirections[cnt-1].z[i] = 1.0f; - - _meanCosines[cnt-1][i] = 0.0f; - _kappas[cnt-1][i] = 0.0f; - _normalizations[cnt-1][i] = ONE_OVER_FOUR_PI; - _eMinus2Kappa[cnt-1][i] = 1.0f; - _distances[cnt-1][i] = 0.0f; + _meanDirections[cnt - 1].x[i] = 0.0f; + _meanDirections[cnt - 1].y[i] = 0.0f; + _meanDirections[cnt - 1].z[i] = 1.0f; + + _meanCosines[cnt - 1][i] = 0.0f; + _kappas[cnt - 1][i] = 0.0f; + _normalizations[cnt - 1][i] = ONE_OVER_FOUR_PI; + _eMinus2Kappa[cnt - 1][i] = 1.0f; + _distances[cnt - 1][i] = 0.0f; } } @@ -803,46 +814,46 @@ float ParallaxAwareVonMisesFisherMixture -float ParallaxAwareVonMisesFisherMixture::pdf( Vector3 direction ) const{ - const int cnt = (_numComponents+VecSize-1) / VecSize; +template +float ParallaxAwareVonMisesFisherMixture::pdf(Vector3 direction) const +{ + const int cnt = (_numComponents + VecSize - 1) / VecSize; embree::vfloat pdf = {0.0f}; - embree::Vec3< embree::vfloat > vec3Direction(direction[0], direction[1], direction[2]); + embree::Vec3> vec3Direction(direction[0], direction[1], direction[2]); const embree::vfloat ones(1.0f); const embree::vfloat zeros(0.0f); - for(int k = 0; k < cnt;k++) + for (int k = 0; k < cnt; k++) { const embree::vfloat cosTheta = embree::dot(vec3Direction, _meanDirections[k]); const embree::vfloat cosThetaMinusOne = embree::min(cosTheta - ones, zeros); - const embree::vfloat eval = _normalizations[k] * embree::fastapprox::exp< embree::vfloat >( _kappas[k] * cosThetaMinusOne ); + const embree::vfloat eval = _normalizations[k] * embree::fastapprox::exp>(_kappas[k] * cosThetaMinusOne); pdf += _weights[k] * eval; } return reduce_add(pdf); } -template -bool ParallaxAwareVonMisesFisherMixture::softAssignment( Vector3 direction, typename ParallaxAwareVonMisesFisherMixture::SoftAssignment &softAssign ) const{ - - const int cnt = (_numComponents+VecSize-1) / VecSize; +template +bool ParallaxAwareVonMisesFisherMixture::softAssignment( + Vector3 direction, typename ParallaxAwareVonMisesFisherMixture::SoftAssignment &softAssign) const +{ + const int cnt = (_numComponents + VecSize - 1) / VecSize; embree::vfloat pdf = {0.0f}; - embree::Vec3< embree::vfloat > vec3Direction(direction[0], direction[1], direction[2]); + embree::Vec3> vec3Direction(direction[0], direction[1], direction[2]); const embree::vfloat ones(1.0f); const embree::vfloat zeros(0.0f); - for(int k = 0; k < cnt;k++) + for (int k = 0; k < cnt; k++) { const embree::vfloat cosTheta = embree::dot(vec3Direction, _meanDirections[k]); const embree::vfloat cosThetaMinusOne = embree::min(cosTheta - ones, zeros); - const embree::vfloat eval = _normalizations[k] * embree::fastapprox::exp< embree::vfloat >( _kappas[k] * cosThetaMinusOne ); - softAssign.assignments[k] = _weights[k] * eval; + const embree::vfloat eval = _normalizations[k] * embree::fastapprox::exp>(_kappas[k] * cosThetaMinusOne); + softAssign.assignments[k] = _weights[k] * eval; OPENPGL_ASSERT(embree::isvalid(softAssign.assignments[k])); pdf += softAssign.assignments[k]; } @@ -850,14 +861,14 @@ bool ParallaxAwareVonMisesFisherMixture inv_pdf = embree::rcp(softAssign.pdf); OPENPGL_ASSERT(embree::isvalid(inv_pdf)); - for(int k = 0; k < cnt;k++) + for (int k = 0; k < cnt; k++) { softAssign.assignments[k] *= inv_pdf; } @@ -865,36 +876,45 @@ bool ParallaxAwareVonMisesFisherMixture -void ParallaxAwareVonMisesFisherMixture::selectComponent(uint32_t &selectedVector, uint32_t &selectedComponent, Vector2 &_sample) const { +template +void ParallaxAwareVonMisesFisherMixture::selectComponent(uint32_t &selectedVector, uint32_t &selectedComponent, + Vector2 &_sample) const +{ float searched = _sample[1]; float sumWeights = 0.0f; float cdf = 0.0f; - //int k0 = 0; - //int k1 = 0; - // find comp + // int k0 = 0; + // int k1 = 0; + // find comp - const div_t tmp = div( _numComponents-1, VecSize); + const div_t tmp = div(_numComponents - 1, VecSize); - while(true){ + while (true) + { cdf = reduce_add(_weights[selectedVector]); - if(sumWeights+cdf >= searched || selectedVector+1 >= (tmp.quot+1)){ + if (sumWeights + cdf >= searched || selectedVector + 1 >= (tmp.quot + 1)) + { break; - }else{ - sumWeights+=cdf; + } + else + { + sumWeights += cdf; selectedVector++; } } - int maxSelectedComponent = selectedVector == tmp.quot ? tmp.rem +1 : VecSize; + int maxSelectedComponent = selectedVector == tmp.quot ? tmp.rem + 1 : VecSize; - while(true){ + while (true) + { cdf = _weights[selectedVector][selectedComponent]; - if(sumWeights+cdf >= searched || selectedComponent+1 >= maxSelectedComponent){ + if (sumWeights + cdf >= searched || selectedComponent + 1 >= maxSelectedComponent) + { break; - }else{ - sumWeights+=cdf; + } + else + { + sumWeights += cdf; selectedComponent++; } } @@ -903,10 +923,11 @@ void ParallaxAwareVonMisesFisherMixture -inline void ParallaxAwareVonMisesFisherMixture::selectComponentSIMD(uint32_t &selectedVector, uint32_t &selectedComponent, Vector2 &_sample) const{ - - embree::vfloat cdfs[NumVectors]; +template +inline void ParallaxAwareVonMisesFisherMixture::selectComponentSIMD(uint32_t &selectedVector, uint32_t &selectedComponent, + Vector2 &_sample) const +{ + embree::vfloat cdfs[NumVectors]; const float searched = _sample[1]; #ifdef VALIDATE_SELECT_COMPONENT_SIMD @@ -915,28 +936,36 @@ inline void ParallaxAwareVonMisesFisherMixture= searched || selectedVector >= tmp.quot){ + cdf = cdfs[selectedVector][VectorSize - 1]; + if (sumWeights + cdf >= searched || selectedVector >= tmp.quot) + { break; - } else { - sumWeights+=cdf; + } + else + { + sumWeights += cdf; } } #else - while(true){ + while (true) + { cdfs[selectedVector] = vinclusive_prefix_sum(_weights[selectedVector]); - cdf = cdfs[selectedVector][VectorSize-1]; - if(sumWeights+cdf >= searched || selectedVector+1 >= (tmp.quot+1)){ + cdf = cdfs[selectedVector][VectorSize - 1]; + if (sumWeights + cdf >= searched || selectedVector + 1 >= (tmp.quot + 1)) + { break; - }else{ - sumWeights+=cdf; + } + else + { + sumWeights += cdf; selectedVector++; } } @@ -945,14 +974,14 @@ inline void ParallaxAwareVonMisesFisherMixture= searched, cdfs[selectedVector]); - - selectedComponent = std::min(selectedComponent, maxSelectedComponent-1); - sumWeights = selectedComponent > 0 ? cdfs[selectedVector][selectedComponent-1] : sumWeights; - + + selectedComponent = std::min(selectedComponent, maxSelectedComponent - 1); + sumWeights = selectedComponent > 0 ? cdfs[selectedVector][selectedComponent - 1] : sumWeights; + cdf = _weights[selectedVector][selectedComponent]; cdf = std::max(FLT_EPSILON, cdf); @@ -965,14 +994,18 @@ inline void ParallaxAwareVonMisesFisherMixture= searchedScalar || selectedVectorScalar+1 >= (tmpScalar.quot+1)){ + if (sumWeightsScalar + cdfScalar >= searchedScalar || selectedVectorScalar + 1 >= (tmpScalar.quot + 1)) + { break; - }else{ - sumWeightsScalar+=cdfScalar; + } + else + { + sumWeightsScalar += cdfScalar; selectedVectorScalar++; } } @@ -981,32 +1014,36 @@ inline void ParallaxAwareVonMisesFisherMixture= searchedScalar || selectedComponentScalar+1 >= maxSelectedComponentScalar){ + if (sumWeightsScalar + cdfScalar >= searchedScalar || selectedComponentScalar + 1 >= maxSelectedComponentScalar) + { break; - }else{ - sumWeightsScalar+=cdfScalar; + } + else + { + sumWeightsScalar += cdfScalar; selectedComponentScalar++; } } - //OPENPGL_ASSERT(selectedComponent == selectedComponentScalar); - //OPENPGL_ASSERT(cdf == cdfScalar); - //OPENPGL_ASSERT(sumWeights == sumWeightsScalar); + // OPENPGL_ASSERT(selectedComponent == selectedComponentScalar); + // OPENPGL_ASSERT(cdf == cdfScalar); + // OPENPGL_ASSERT(sumWeights == sumWeightsScalar); _sampleScalar[1] = std::min(1 - FLT_EPSILON, (searchedScalar - sumWeightsScalar) / cdfScalar); - //OPENPGL_ASSERT(_sample[1] == _sampleScalar[1]); + // OPENPGL_ASSERT(_sample[1] == _sampleScalar[1]); #endif } #endif -template -Vector3 ParallaxAwareVonMisesFisherMixture::sample( const Vector2 sample ) const{ - - uint32_t selectedVector {0}; - uint32_t selectedComponent {0}; +template +Vector3 ParallaxAwareVonMisesFisherMixture::sample(const Vector2 sample) const +{ + uint32_t selectedVector{0}; + uint32_t selectedComponent{0}; // First, identify component we want to sample Vector2 _sample = sample; @@ -1016,26 +1053,27 @@ Vector3 ParallaxAwareVonMisesFisherMixture sampledDirection(0.f, 0.f, 1.f); + embree::Vec3 sampledDirection(0.f, 0.f, 1.f); // Second, sample selected component const float sKappa = _kappas[selectedVector][selectedComponent]; const float sEMinus2Kappa = _eMinus2Kappa[selectedVector][selectedComponent]; - const embree::Vec3 meanDirection( _meanDirections[selectedVector].x[selectedComponent], _meanDirections[selectedVector].y[selectedComponent], _meanDirections[selectedVector].z[selectedComponent]); + const embree::Vec3 meanDirection(_meanDirections[selectedVector].x[selectedComponent], _meanDirections[selectedVector].y[selectedComponent], + _meanDirections[selectedVector].z[selectedComponent]); if (sKappa == 0.0f) { - sampledDirection = squareToUniformSphere( _sample ); + sampledDirection = squareToUniformSphere(_sample); } else { - float cosTheta = 1.f + (embree::fastapprox::log(1.0f + ((sEMinus2Kappa-1.f) * _sample[0]))) / sKappa; - //float cosTheta = 1.f + (std::log1p((sEMinus2Kappa-1.f) * _sample[0])) / sKappa; + float cosTheta = 1.f + (embree::fastapprox::log(1.0f + ((sEMinus2Kappa - 1.f) * _sample[0]))) / sKappa; + // float cosTheta = 1.f + (std::log1p((sEMinus2Kappa-1.f) * _sample[0])) / sKappa; // safeguard for numerical imprecisions (if sample[0] is 0.999999999) cosTheta = std::min(1.0f, std::max(cosTheta, -1.f)); - const float sinTheta = std::sqrt(1.f-cosTheta*cosTheta); + const float sinTheta = std::sqrt(1.f - cosTheta * cosTheta); const float phi = 2.f * M_PI_F * _sample[1]; @@ -1044,22 +1082,23 @@ Vector3 ParallaxAwareVonMisesFisherMixture -void ParallaxAwareVonMisesFisherMixture::performRelativeParallaxShift( const Vector3 &shiftDirection ) +template +void ParallaxAwareVonMisesFisherMixture::performRelativeParallaxShift(const Vector3 &shiftDirection) { const embree::vfloat ones(1.0f); const embree::vfloat zeros(0.0f); - const int cnt = (this->_numComponents+VectorSize-1) / VectorSize; - //const int rem = this->_numComponents % VectorSize; + const int cnt = (this->_numComponents + VectorSize - 1) / VectorSize; + // const int rem = this->_numComponents % VectorSize; - const embree::Vec3 > shiftDirectionVec(shiftDirection); - embree::Vec3 > parallaxCorrectedMeanDirections; + const embree::Vec3> shiftDirectionVec(shiftDirection); + embree::Vec3> parallaxCorrectedMeanDirections; embree::vfloat lengths; - for(uint32_t k=0;k_meanDirections[k] * _distances[k] + shiftDirectionVec; lengths = embree::length(parallaxCorrectedMeanDirections); parallaxCorrectedMeanDirections /= lengths; @@ -1072,118 +1111,113 @@ void ParallaxAwareVonMisesFisherMixture -void ParallaxAwareVonMisesFisherMixture::_normalizeWeights( ) { - - const int cnt = (_numComponents+VecSize-1) / VecSize; +template +void ParallaxAwareVonMisesFisherMixture::_normalizeWeights() +{ + const int cnt = (_numComponents + VecSize - 1) / VecSize; embree::vfloat sumWeights = 0.0f; - for(int k = 0; k < cnt;k++){ + for (int k = 0; k < cnt; k++) + { sumWeights += _weights[k]; } embree::vfloat inv_sumWeights = 1.0f / reduce_add(sumWeights); - for(int k = 0; k < cnt;k++){ + for (int k = 0; k < cnt; k++) + { _weights[k] *= inv_sumWeights; } - } -template -void ParallaxAwareVonMisesFisherMixture::_calculateNormalization( ) { +template +void ParallaxAwareVonMisesFisherMixture::_calculateNormalization() +{ const embree::vfloat zeroKappaNorm(ONE_OVER_FOUR_PI); - const int cnt = (_numComponents+VecSize-1) / VecSize; + const int cnt = (_numComponents + VecSize - 1) / VecSize; const embree::vfloat minusTwo(-2.0f); - for(int k = 0; k < cnt;k++){ - _eMinus2Kappa[k] = embree::fastapprox::exp< embree::vfloat >(minusTwo*_kappas[k]); - const embree::vfloat norm = _kappas[k]/(2.0f*M_PI_F*(1.0f-_eMinus2Kappa[k])); + for (int k = 0; k < cnt; k++) + { + _eMinus2Kappa[k] = embree::fastapprox::exp>(minusTwo * _kappas[k]); + const embree::vfloat norm = _kappas[k] / (2.0f * M_PI_F * (1.0f - _eMinus2Kappa[k])); _normalizations[k] = select(_kappas[k] > 0.f, norm, zeroKappaNorm); } - } -template -void ParallaxAwareVonMisesFisherMixture::_calculateMeanCosines( ) { - - const int cnt = (_numComponents+VecSize-1) / VecSize; +template +void ParallaxAwareVonMisesFisherMixture::_calculateMeanCosines() +{ + const int cnt = (_numComponents + VecSize - 1) / VecSize; const embree::vfloat zeros(0.0f); const embree::vfloat ones(1.0f); - for(int k = 0; k < cnt;k++){ - embree::vfloat tanh = ones - 2.0f / ( embree::fastapprox::exp( 2.0f * _kappas[k] ) - ones ); - embree::vfloat meanCosine = ones /tanh - ones / _kappas[k]; - //std::cout << "meanCosine: " << meanCosine << std::endl; + for (int k = 0; k < cnt; k++) + { + embree::vfloat tanh = ones - 2.0f / (embree::fastapprox::exp(2.0f * _kappas[k]) - ones); + embree::vfloat meanCosine = ones / tanh - ones / _kappas[k]; + // std::cout << "meanCosine: " << meanCosine << std::endl; _meanCosines[k] = select(_kappas[k] > 0.f, meanCosine, zeros); } } -template -bool ParallaxAwareVonMisesFisherMixture::operator==(const ParallaxAwareVonMisesFisherMixture& b) const +template +bool ParallaxAwareVonMisesFisherMixture::operator==(const ParallaxAwareVonMisesFisherMixture &b) const { bool equal = true; - if(_numComponents != b._numComponents || _pivotPosition != b._pivotPosition) + if (_numComponents != b._numComponents || _pivotPosition != b._pivotPosition) { equal = false; } - - for(int k = 0; k < NumVectors; k++) + + for (int k = 0; k < NumVectors; k++) { - - if( embree::any(_weights[k] != b._weights[k]) || - embree::any(_kappas[k] != b._kappas[k]) || - embree::any(_meanDirections[k].x != b._meanDirections[k].x) || - embree::any(_meanDirections[k].y != b._meanDirections[k].y) || - embree::any(_meanDirections[k].z != b._meanDirections[k].z) || - embree::any(_normalizations[k] != b._normalizations[k]) || - embree::any(_eMinus2Kappa[k] != b._eMinus2Kappa[k]) || - embree::any(_meanCosines[k] != b._meanCosines[k]) || + if (embree::any(_weights[k] != b._weights[k]) || embree::any(_kappas[k] != b._kappas[k]) || embree::any(_meanDirections[k].x != b._meanDirections[k].x) || + embree::any(_meanDirections[k].y != b._meanDirections[k].y) || embree::any(_meanDirections[k].z != b._meanDirections[k].z) || + embree::any(_normalizations[k] != b._normalizations[k]) || embree::any(_eMinus2Kappa[k] != b._eMinus2Kappa[k]) || embree::any(_meanCosines[k] != b._meanCosines[k]) || embree::any(_distances[k] != b._distances[k])) { equal = false; } - } return equal; } #ifdef OPENPGL_RADIANCE_CACHES -template -Vector3 ParallaxAwareVonMisesFisherMixture::incomingRadiance( const Vector3 &direction, const bool directLightMIS) const{ - const int cnt = (_numComponents+VecSize-1) / VecSize; +template +Vector3 ParallaxAwareVonMisesFisherMixture::incomingRadiance(const Vector3 &direction, const bool directLightMIS) const +{ + const int cnt = (_numComponents + VecSize - 1) / VecSize; - embree::Vec3< embree::vfloat > incomingRadiance = {0.0f, 0.0f, 0.0f}; - embree::Vec3< embree::vfloat > vec3Direction(direction[0], direction[1], direction[2]); + embree::Vec3> incomingRadiance = {0.0f, 0.0f, 0.0f}; + embree::Vec3> vec3Direction(direction[0], direction[1], direction[2]); const embree::vfloat ones(1.0f); const embree::vfloat zeros(0.0f); - for(int k = 0; k < cnt;k++) + for (int k = 0; k < cnt; k++) { const embree::vfloat cosTheta = embree::dot(vec3Direction, _meanDirections[k]); const embree::vfloat cosThetaMinusOne = embree::min(cosTheta - ones, zeros); - const embree::vfloat eval = _normalizations[k] * embree::fastapprox::exp< embree::vfloat >( _kappas[k] * cosThetaMinusOne ); + const embree::vfloat eval = _normalizations[k] * embree::fastapprox::exp>(_kappas[k] * cosThetaMinusOne); incomingRadiance += directLightMIS ? _fluenceRGBWeightsWithMIS[k] * eval : _fluenceRGBWeights[k] * eval; } return Vector3(reduce_add(incomingRadiance.x), reduce_add(incomingRadiance.y), reduce_add(incomingRadiance.z)); } +template +Vector3 ParallaxAwareVonMisesFisherMixture::irradiance(const Vector3 &normal, const bool directLightMIS) const +{ + const embree::vfloat cosine_meanCosine(KappaToMeanCosine(2.18853f)); // TODO -template -Vector3 ParallaxAwareVonMisesFisherMixture::irradiance( const Vector3 &normal, const bool directLightMIS) const{ - const embree::vfloat cosine_meanCosine(KappaToMeanCosine(2.18853f)); // TODO - - const int cnt = (_numComponents+VecSize-1) / VecSize; + const int cnt = (_numComponents + VecSize - 1) / VecSize; - embree::Vec3< embree::vfloat > irradiance = {0.0f, 0.0f, 0.0f}; - embree::Vec3< embree::vfloat > vec3Normal(normal[0], normal[1], normal[2]); + embree::Vec3> irradiance = {0.0f, 0.0f, 0.0f}; + embree::Vec3> vec3Normal(normal[0], normal[1], normal[2]); const embree::vfloat ones(1.0f); const embree::vfloat zeros(0.0f); - for(int k = 0; k < cnt;k++) + for (int k = 0; k < cnt; k++) { const embree::vfloat eval = _convolvePDF(k, vec3Normal, cosine_meanCosine); irradiance += directLightMIS ? _fluenceRGBWeightsWithMIS[k] * eval : _fluenceRGBWeights[k] * eval; @@ -1191,20 +1225,21 @@ Vector3 ParallaxAwareVonMisesFisherMixture -Vector3 ParallaxAwareVonMisesFisherMixture::inscatteredRadiance( const Vector3 &dir, const float meanCosine, const bool directLightMIS) const{ +template +Vector3 ParallaxAwareVonMisesFisherMixture::inscatteredRadiance(const Vector3 &dir, const float meanCosine, + const bool directLightMIS) const +{ const embree::vfloat meanCosineVec(meanCosine); - const int cnt = (_numComponents+VecSize-1) / VecSize; + const int cnt = (_numComponents + VecSize - 1) / VecSize; - embree::Vec3< embree::vfloat > inscatteredRadiance = {0.0f, 0.0f, 0.0f}; - embree::Vec3< embree::vfloat > vec3Dir(-dir[0], -dir[1], -dir[2]); + embree::Vec3> inscatteredRadiance = {0.0f, 0.0f, 0.0f}; + embree::Vec3> vec3Dir(-dir[0], -dir[1], -dir[2]); const embree::vfloat ones(1.0f); const embree::vfloat zeros(0.0f); - for(int k = 0; k < cnt;k++) + for (int k = 0; k < cnt; k++) { const embree::vfloat eval = _convolvePDF(k, vec3Dir, meanCosineVec); inscatteredRadiance += directLightMIS ? _fluenceRGBWeightsWithMIS[k] * eval : _fluenceRGBWeights[k] * eval; @@ -1212,22 +1247,26 @@ Vector3 ParallaxAwareVonMisesFisherMixture -Vector3 ParallaxAwareVonMisesFisherMixture::fluence(const bool directLightMIS) const{ +template +Vector3 ParallaxAwareVonMisesFisherMixture::fluence(const bool directLightMIS) const +{ return directLightMIS ? _fluenceRGBWithMIS : _fluenceRGB; } #endif -template -embree::vfloat ParallaxAwareVonMisesFisherMixture::_convolvePDF(const size_t k, const embree::Vec3< embree::vfloat >& normal, const embree::vfloat& meanCosine1) const { +template +embree::vfloat ParallaxAwareVonMisesFisherMixture::_convolvePDF(const size_t k, + const embree::Vec3> &normal, + const embree::vfloat &meanCosine1) const +{ const embree::vfloat ones(1.0f); const embree::vfloat zeros(0.0f); const embree::vfloat invFourPi(1.0f / (4.0f * M_PI_F)); - + const embree::vfloat cosTheta = embree::dot(normal, _meanDirections[k]); - + const embree::vfloat meanCosine0 = _meanCosines[k]; - + const embree::vfloat meanCosine = meanCosine0 * meanCosine1; OPENPGL_ASSERT(embree::is_finite(meanCosine)); @@ -1245,24 +1284,23 @@ embree::vfloat ParallaxAwareVonMisesFisherMixture +template inline Type KappaToMeanCosine(const Type &kappa) { const Type ones(1.0f); const Type zeros(0.0f); - Type meanCosine = ones / embree::tanh( kappa) - ones / kappa; - return embree::select( kappa > 0.f, meanCosine, zeros); + Type meanCosine = ones / embree::tanh(kappa) - ones / kappa; + return embree::select(kappa > 0.f, meanCosine, zeros); } - -template +template inline Type MeanCosineToKappa(const Type &meanCosine) { const Type ones(1.0f); const Type dim(3.0f); const Type meanCosine2 = meanCosine * meanCosine; - return ( meanCosine * dim - meanCosine * meanCosine2) / ( ones - meanCosine2 ); + return (meanCosine * dim - meanCosine * meanCosine2) / (ones - meanCosine2); } -} +} // namespace openpgl diff --git a/openpgl/directional/vmm/ParallaxAwareVonMisesFisherWeightedEMFactory.h b/openpgl/directional/vmm/ParallaxAwareVonMisesFisherWeightedEMFactory.h index 242a102..44c8b0c 100644 --- a/openpgl/directional/vmm/ParallaxAwareVonMisesFisherWeightedEMFactory.h +++ b/openpgl/directional/vmm/ParallaxAwareVonMisesFisherWeightedEMFactory.h @@ -3,67 +3,64 @@ #pragma once -#include "../../openpgl_common.h" -#include "../../data/SampleData.h" -#include "ParallaxAwareVonMisesFisherMixture.h" - #include #include -//#define OPENPGL_MAX_KAPPA 1000000.0f +#include "../../data/SampleData.h" +#include "../../openpgl_common.h" +#include "ParallaxAwareVonMisesFisherMixture.h" + +// #define OPENPGL_MAX_KAPPA 1000000.0f #define OPENPGL_MAX_KAPPA 32000.0f #define USE_HARMONIC_MEAN #define MC_ESTIMATE_INCOMING_RADIANCE -//using namespace embree; +// using namespace embree; namespace openpgl { -template +template struct ParallaxAwareVonMisesFisherWeightedEMFactory { - -public: - + public: typedef TVMMDistribution Distribution; using VMM = TVMMDistribution; struct Configuration { - size_t initK {VMM::VectorSize}; - float initKappa {5.0f}; + size_t initK{VMM::VectorSize}; + float initKappa{5.0f}; - size_t maxK {VMM::MaxComponents}; - size_t maxEMIterrations {100}; + size_t maxK{VMM::MaxComponents}; + size_t maxEMIterrations{100}; - float maxKappa {OPENPGL_MAX_KAPPA}; - float maxMeanCosine { KappaToMeanCosine(OPENPGL_MAX_KAPPA)}; - float convergenceThreshold {0.0025f}; + float maxKappa{OPENPGL_MAX_KAPPA}; + float maxMeanCosine{KappaToMeanCosine(OPENPGL_MAX_KAPPA)}; + float convergenceThreshold{0.0025f}; // MAP prior parameters // weight prior float weightPrior{0.1f}; // concentration/meanCosine prior - float meanCosinePriorStrength {0.1f}; - float meanCosinePrior {0.0f}; + float meanCosinePriorStrength{0.1f}; + float meanCosinePrior{0.0f}; void init(); - void serialize(std::ostream& stream) const; + void serialize(std::ostream &stream) const; - void deserialize(std::istream& stream); + void deserialize(std::istream &stream); std::string toString() const; - bool operator==(const Configuration& b) const { + bool operator==(const Configuration &b) const + { bool equal = true; - if(initK != b.initK || initKappa != b.initKappa || - maxK != b.maxK || maxEMIterrations != b.maxEMIterrations || - maxKappa != b.maxKappa || maxMeanCosine != b.maxMeanCosine || - convergenceThreshold != b.convergenceThreshold || weightPrior != b.weightPrior || + if (initK != b.initK || initKappa != b.initKappa || maxK != b.maxK || maxEMIterrations != b.maxEMIterrations || maxKappa != b.maxKappa || + maxMeanCosine != b.maxMeanCosine || convergenceThreshold != b.convergenceThreshold || weightPrior != b.weightPrior || meanCosinePriorStrength != b.meanCosinePriorStrength || meanCosinePrior != b.meanCosinePrior) { equal = false; @@ -74,9 +71,9 @@ struct ParallaxAwareVonMisesFisherWeightedEMFactory struct FittingStatistics { - size_t numSamples {0}; - size_t numIterations {0}; - float summedWeightedLogLikelihood {0.0f}; + size_t numSamples{0}; + size_t numIterations{0}; + float summedWeightedLogLikelihood{0.0f}; }; struct PartialFittingMask @@ -92,35 +89,34 @@ struct ParallaxAwareVonMisesFisherWeightedEMFactory std::string toString() const; }; - struct SufficientStatistics//: public WEMVMMFactory::SufficientStatistics + struct SufficientStatistics //: public WEMVMMFactory::SufficientStatistics { - - //FittingStatistics - public: - embree::Vec3< embree::vfloat > sumOfWeightedDirections[VMM::NumVectors]; + // FittingStatistics + public: + embree::Vec3 > sumOfWeightedDirections[VMM::NumVectors]; embree::vfloat sumOfWeightedStats[VMM::NumVectors]; - float sumWeights {0.f}; - float numSamples {0.f}; - float overallNumSamples {0.f}; - size_t numComponents {VMM::MaxComponents}; - bool normalized {false}; + float sumWeights{0.f}; + float numSamples{0.f}; + float overallNumSamples{0.f}; + size_t numComponents{VMM::MaxComponents}; + bool normalized{false}; embree::vfloat sumOfDistanceWeightes[VMM::NumVectors]; SufficientStatistics() = default; - SufficientStatistics& operator+=(const SufficientStatistics &stats); + SufficientStatistics &operator+=(const SufficientStatistics &stats); - void serialize(std::ostream& stream) const; + void serialize(std::ostream &stream) const; - void deserialize(std::istream& stream); + void deserialize(std::istream &stream); void clear(size_t _numComponents); void clearAll(); - virtual void normalize( const float &_numSamples ); + virtual void normalize(const float &_numSamples); inline bool isNormalized() const { @@ -129,9 +125,8 @@ struct ParallaxAwareVonMisesFisherWeightedEMFactory void mergeComponentStats(const size_t &idx0, const size_t &idx1); - void splitComponentsStats(const size_t &idx0, const size_t &idx1, - const Vector3 &meanDirection0, const Vector3 &meanDirection1, - const float &meanCosine0, const float &meanCosine1); + void splitComponentsStats(const size_t &idx0, const size_t &idx1, const Vector3 &meanDirection0, const Vector3 &meanDirection1, const float &meanCosine0, + const float &meanCosine1); void swapComponentStats(const size_t &idx0, const size_t &idx1); @@ -151,12 +146,12 @@ struct ParallaxAwareVonMisesFisherWeightedEMFactory return sumWeights; } - inline void setNumComponents( const size_t &numComponents) + inline void setNumComponents(const size_t &numComponents) { this->numComponents = numComponents; } - inline size_t getNumComponents( ) const + inline size_t getNumComponents() const { return this->numComponents; } @@ -165,8 +160,7 @@ struct ParallaxAwareVonMisesFisherWeightedEMFactory bool isValid() const; - bool operator==(const SufficientStatistics& b) const; - + bool operator==(const SufficientStatistics &b) const; }; struct UnassignedSamplesStatistics @@ -177,22 +171,23 @@ struct ParallaxAwareVonMisesFisherWeightedEMFactory bool isValid() const; }; -public: - + public: ParallaxAwareVonMisesFisherWeightedEMFactory(); - void InitUniformVMM( VMM &vmm, const int &numComponents, const float &kappa) const; + void InitUniformVMM(VMM &vmm, const int &numComponents, const float &kappa) const; + + void prepareSamples(SampleData *samples, const size_t numSamples, const SampleStatistics &sampleStatistics, const Configuration &cfg) const; - void prepareSamples(SampleData* samples, const size_t numSamples, const SampleStatistics &sampleStatistics, const Configuration &cfg) const; - - void fitMixture(VMM &vmm, SufficientStatistics &stats, const SampleData* samples, const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) const; + void fitMixture(VMM &vmm, SufficientStatistics &stats, const SampleData *samples, const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) const; - void updateMixture(VMM &vmm, SufficientStatistics &previousStats, const SampleData* samples, const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) const; + void updateMixture(VMM &vmm, SufficientStatistics &previousStats, const SampleData *samples, const size_t numSamples, const Configuration &cfg, + FittingStatistics &fitStats) const; - void partialUpdateMixture(VMM &vmm, PartialFittingMask &mask, SufficientStatistics &previousStats, const SampleData* samples, const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) const; + void partialUpdateMixture(VMM &vmm, PartialFittingMask &mask, SufficientStatistics &previousStats, const SampleData *samples, const size_t numSamples, const Configuration &cfg, + FittingStatistics &fitStats) const; #ifdef OPENPGL_RADIANCE_CACHES - void updateFluenceEstimate(VMM &vmm, const SampleData* samples, const size_t numSamples, const size_t numZeroValueSamples, const SampleStatistics &sampleStatistics) const; + void updateFluenceEstimate(VMM &vmm, const SampleData *samples, const size_t numSamples, const size_t numZeroValueSamples, const SampleStatistics &sampleStatistics) const; #endif VMM VMMfromSufficientStatistics(const SufficientStatistics &suffStats, const Configuration &cfg) const; @@ -202,58 +197,55 @@ struct ParallaxAwareVonMisesFisherWeightedEMFactory return "ParallaxAwareVonMisesFisherWeightedEMFactory"; }; - void initComponentDistances (VMM &vmm, SufficientStatistics &sufficientStats, const SampleData* samples, const size_t numSamples) const; + void initComponentDistances(VMM &vmm, SufficientStatistics &sufficientStats, const SampleData *samples, const size_t numSamples) const; - void updateComponentDistances (VMM &vmm, SufficientStatistics &sufficientStats, const SampleData* samples, const size_t numSamples) const; + void updateComponentDistances(VMM &vmm, SufficientStatistics &sufficientStats, const SampleData *samples, const size_t numSamples) const; -private: + private: void _initUniformDirections(); - float weightedExpectationStep(VMM &vmm, SufficientStatistics &stats, UnassignedSamplesStatistics &unassignedStats, const SampleData* samples, const size_t numSamples) const; + float weightedExpectationStep(VMM &vmm, SufficientStatistics &stats, UnassignedSamplesStatistics &unassignedStats, const SampleData *samples, const size_t numSamples) const; - void weightedMaximumAPosteriorStep(VMM &vmm, const SufficientStatistics &previousStats, - const SufficientStatistics ¤tStats, - const Configuration &cfg) const; + void weightedMaximumAPosteriorStep(VMM &vmm, const SufficientStatistics &previousStats, const SufficientStatistics ¤tStats, const Configuration &cfg) const; - void estimateMAPWeights( VMM &vmm, const SufficientStatistics ¤tStats, const SufficientStatistics &previousStats, const float &_weightPrior ) const; + void estimateMAPWeights(VMM &vmm, const SufficientStatistics ¤tStats, const SufficientStatistics &previousStats, const float &_weightPrior) const; - void estimateMAPMeanDirectionAndConcentration( VMM &vmm, const SufficientStatistics ¤tStats, const SufficientStatistics &previousStats, const Configuration &cfg) const; + void estimateMAPMeanDirectionAndConcentration(VMM &vmm, const SufficientStatistics ¤tStats, const SufficientStatistics &previousStats, const Configuration &cfg) const; - void partialWeightedMaximumAPosteriorStep(VMM &vmm, const PartialFittingMask &mask, SufficientStatistics &previousStats, - SufficientStatistics ¤tStats, - const Configuration &cfg) const; + void partialWeightedMaximumAPosteriorStep(VMM &vmm, const PartialFittingMask &mask, SufficientStatistics &previousStats, SufficientStatistics ¤tStats, + const Configuration &cfg) const; - void estimatePartialMAPWeights( VMM &vmm, const PartialFittingMask &mask, SufficientStatistics ¤tStats, SufficientStatistics &previousStats, const float &_weightPrior ) const; + void estimatePartialMAPWeights(VMM &vmm, const PartialFittingMask &mask, SufficientStatistics ¤tStats, SufficientStatistics &previousStats, + const float &_weightPrior) const; - void estimatePartialMAPMeanDirectionAndConcentration( VMM &vmm, const PartialFittingMask &mask, SufficientStatistics ¤tStats, SufficientStatistics &previousStats, const Configuration &cfg) const; + void estimatePartialMAPMeanDirectionAndConcentration(VMM &vmm, const PartialFittingMask &mask, SufficientStatistics ¤tStats, SufficientStatistics &previousStats, + const Configuration &cfg) const; void handleUnassignedSampleStats(UnassignedSamplesStatistics &unassignedStats, VMM &vmm, SufficientStatistics ¤tStats, SufficientStatistics &previousStats) const; - void reprojectSample(openpgl::SampleData &sample, const openpgl::Point3 &pivotPoint, const float minDistance) const; -private: - embree::Vec3< embree::vfloat >_uniformDirections[VMM::MaxComponents][VMM::NumVectors]; - + private: + embree::Vec3 > _uniformDirections[VMM::MaxComponents][VMM::NumVectors]; }; //////////////////////////////////////////////////////////// ///////// UnassignedSamplesStatistics //////////////////////////////////////////////////////////// -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::UnassignedSamplesStatistics::clear() +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::UnassignedSamplesStatistics::clear() { sumOfUnassignedWeights = 0.0f; sumUnassignedWeightedDirections = Vector3(0.0f); } -template -bool ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::UnassignedSamplesStatistics::isValid() const +template +bool ParallaxAwareVonMisesFisherWeightedEMFactory::UnassignedSamplesStatistics::isValid() const { bool valid = true; valid = valid && embree::isvalid(sumOfUnassignedWeights); - valid = valid && sumOfUnassignedWeights>=0.f; + valid = valid && sumOfUnassignedWeights >= 0.f; OPENPGL_ASSERT(valid); valid = valid && embree::isvalid(sumUnassignedWeightedDirections.x); @@ -267,19 +259,19 @@ bool ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Unassigned ///////// SufficientStatistics //////////////////////////////////////////////////////////// -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::SufficientStatistics::applyParallaxShift(const VMM &vmm, const Vector3 shift) +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::SufficientStatistics::applyParallaxShift(const VMM &vmm, const Vector3 shift) { - const int cnt = (vmm._numComponents+VMM::VectorSize-1) / VMM::VectorSize; - //const int rem = vmm._numComponents % VMM::VectorSize; + const int cnt = (vmm._numComponents + VMM::VectorSize - 1) / VMM::VectorSize; + // const int rem = vmm._numComponents % VMM::VectorSize; - for(uint32_t k=0;k > suffDirections = sumOfWeightedDirections[k]; + embree::Vec3 > suffDirections = sumOfWeightedDirections[k]; embree::vfloat suffMeanCosines = embree::length(suffDirections); suffDirections /= suffMeanCosines; suffDirections *= vmm._distances[k]; - suffDirections += embree::Vec3< embree::vfloat >(shift); + suffDirections += embree::Vec3 >(shift); suffDirections /= embree::length(suffDirections); suffDirections *= suffMeanCosines; @@ -288,24 +280,24 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Sufficient } } -template -bool ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::SufficientStatistics::isValid() const +template +bool ParallaxAwareVonMisesFisherWeightedEMFactory::SufficientStatistics::isValid() const { bool valid = true; - for(size_t k = 0; k < numComponents; k++) + for (size_t k = 0; k < numComponents; k++) { - const div_t tmpK = div( k, VMM::VectorSize ); + const div_t tmpK = div(k, VMM::VectorSize); valid = valid && embree::isvalid(sumOfWeightedDirections[tmpK.quot].x[tmpK.rem]); - //valid = valid && sumOfWeightedDirections[tmpK.quot][tmpK.rem] >= 0.0f; + // valid = valid && sumOfWeightedDirections[tmpK.quot][tmpK.rem] >= 0.0f; OPENPGL_ASSERT(valid); valid = valid && embree::isvalid(sumOfWeightedDirections[tmpK.quot].y[tmpK.rem]); - //valid = valid && sumOfWeightedDirections[tmpK.quot][tmpK.rem] >= 0.0f; + // valid = valid && sumOfWeightedDirections[tmpK.quot][tmpK.rem] >= 0.0f; OPENPGL_ASSERT(valid); valid = valid && embree::isvalid(sumOfWeightedDirections[tmpK.quot].z[tmpK.rem]); - //valid = valid && sumOfWeightedDirections[tmpK.quot][tmpK.rem] >= 0.0f; + // valid = valid && sumOfWeightedDirections[tmpK.quot][tmpK.rem] >= 0.0f; OPENPGL_ASSERT(valid); valid = valid && embree::isvalid(sumOfWeightedStats[tmpK.quot][tmpK.rem]); @@ -317,9 +309,9 @@ bool ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Sufficient OPENPGL_ASSERT(valid); } - for(size_t k = numComponents; k < VMM::MaxComponents; k++) + for (size_t k = numComponents; k < VMM::MaxComponents; k++) { - const div_t tmpK = div( k, VMM::VectorSize ); + const div_t tmpK = div(k, VMM::VectorSize); valid = valid && sumOfWeightedDirections[tmpK.quot].x[tmpK.rem] == 0.0f; OPENPGL_ASSERT(valid); @@ -348,42 +340,42 @@ bool ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Sufficient return valid; } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::SufficientStatistics::serialize(std::ostream& stream) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::SufficientStatistics::serialize(std::ostream &stream) const { serializeVec3Vectors(stream, sumOfWeightedDirections); serializeFloatVectors(stream, sumOfWeightedStats); serializeFloatVectors(stream, sumOfDistanceWeightes); - stream.write(reinterpret_cast(&sumWeights), sizeof(float)); - stream.write(reinterpret_cast(&numSamples), sizeof(float)); - stream.write(reinterpret_cast(&overallNumSamples), sizeof(float)); - stream.write(reinterpret_cast(&numComponents), sizeof(size_t)); - stream.write(reinterpret_cast(&normalized), sizeof(bool)); + stream.write(reinterpret_cast(&sumWeights), sizeof(float)); + stream.write(reinterpret_cast(&numSamples), sizeof(float)); + stream.write(reinterpret_cast(&overallNumSamples), sizeof(float)); + stream.write(reinterpret_cast(&numComponents), sizeof(size_t)); + stream.write(reinterpret_cast(&normalized), sizeof(bool)); } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::SufficientStatistics::deserialize(std::istream& stream) +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::SufficientStatistics::deserialize(std::istream &stream) { deserializeVec3Vectors(stream, sumOfWeightedDirections); deserializeFloatVectors(stream, sumOfWeightedStats); deserializeFloatVectors(stream, sumOfDistanceWeightes); - stream.read(reinterpret_cast(&sumWeights), sizeof(float)); - stream.read(reinterpret_cast(&numSamples), sizeof(float)); - stream.read(reinterpret_cast(&overallNumSamples), sizeof(float)); - stream.read(reinterpret_cast(&numComponents), sizeof(size_t)); - stream.read(reinterpret_cast(&normalized), sizeof(bool)); + stream.read(reinterpret_cast(&sumWeights), sizeof(float)); + stream.read(reinterpret_cast(&numSamples), sizeof(float)); + stream.read(reinterpret_cast(&overallNumSamples), sizeof(float)); + stream.read(reinterpret_cast(&numComponents), sizeof(size_t)); + stream.read(reinterpret_cast(&normalized), sizeof(bool)); } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::SufficientStatistics::clear(size_t _numComponents) +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::SufficientStatistics::clear(size_t _numComponents) { - const embree::Vec3< embree::vfloat > vecZeros(0.0f); + const embree::Vec3 > vecZeros(0.0f); const embree::vfloat zeros(0.0f); numComponents = _numComponents; - const int cnt = (numComponents+VMM::VectorSize-1) / VMM::VectorSize; + const int cnt = (numComponents + VMM::VectorSize - 1) / VMM::VectorSize; - for(int k = 0; k < cnt;k++) + for (int k = 0; k < cnt; k++) { sumOfWeightedDirections[k] = vecZeros; sumOfWeightedStats[k] = zeros; @@ -396,22 +388,22 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Sufficient normalized = false; } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::SufficientStatistics::clearAll() +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::SufficientStatistics::clearAll() { clear(VMM::MaxComponents); } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::SufficientStatistics::decay(const float &alpha) +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::SufficientStatistics::decay(const float &alpha) { - for(int k = 0; k < VMM::NumVectors; k++) + for (int k = 0; k < VMM::NumVectors; k++) { sumOfWeightedDirections[k].x *= alpha; sumOfWeightedDirections[k].y *= alpha; sumOfWeightedDirections[k].z *= alpha; sumOfWeightedStats[k] *= alpha; - + sumOfDistanceWeightes[k] *= alpha; } @@ -419,8 +411,8 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Sufficient sumWeights *= alpha; } -template -std::string ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::SufficientStatistics::toString() const +template +std::string ParallaxAwareVonMisesFisherWeightedEMFactory::SufficientStatistics::toString() const { std::stringstream ss; ss << "SufficientStatistics:" << std::endl; @@ -429,30 +421,26 @@ std::string ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Suf ss << "\toverallNumSamples = " << overallNumSamples << std::endl; ss << "\tnumComponents = " << numComponents << std::endl; ss << "\tisNormalized = " << normalized << std::endl; - //for (size_t k = 0; k < numComponents ; k++) - for (size_t k = 0; k < VMM::MaxComponents ; k++) + // for (size_t k = 0; k < numComponents ; k++) + for (size_t k = 0; k < VMM::MaxComponents; k++) { int i = k / VMM::VectorSize; int j = k % VMM::VectorSize; - ss << "\tstat["<< k <<"]:" << "\tsumWeightedStats = " << sumOfWeightedStats[i][j] - << "\tsumWeightedDirections = [" << sumOfWeightedDirections[i].x[j] << ",\t" - << sumOfWeightedDirections[i].y[j] << ",\t" << sumOfWeightedDirections[i].z[j] << "]" - << "\tsumWeightedDistanceWeights = " << sumOfDistanceWeightes[i][j] - << std::endl; + ss << "\tstat[" << k << "]:" << "\tsumWeightedStats = " << sumOfWeightedStats[i][j] << "\tsumWeightedDirections = [" << sumOfWeightedDirections[i].x[j] << ",\t" + << sumOfWeightedDirections[i].y[j] << ",\t" << sumOfWeightedDirections[i].z[j] << "]" << "\tsumWeightedDistanceWeights = " << sumOfDistanceWeightes[i][j] << std::endl; } return ss.str(); } - -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::SufficientStatistics::maskedReplace(const PartialFittingMask &mask, const SufficientStatistics &stats) +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::SufficientStatistics::maskedReplace(const PartialFittingMask &mask, const SufficientStatistics &stats) { - embree::vfloat newSumWeights {0.0f}; + embree::vfloat newSumWeights{0.0f}; - for (size_t k = 0; k < ( (VMM::MaxComponents + (VMM::VectorSize -1)) / VMM::VectorSize); k++) + for (size_t k = 0; k < ((VMM::MaxComponents + (VMM::VectorSize - 1)) / VMM::VectorSize); k++) { sumOfWeightedDirections[k] = select(mask.mask[k], stats.sumOfWeightedDirections[k], sumOfWeightedDirections[k]); - sumOfWeightedStats[k] = select(mask.mask[k], stats.sumOfWeightedStats[k], sumOfWeightedStats[k]); + sumOfWeightedStats[k] = select(mask.mask[k], stats.sumOfWeightedStats[k], sumOfWeightedStats[k]); newSumWeights += sumOfWeightedStats[k]; sumOfDistanceWeightes[k] = select(mask.mask[k], stats.sumOfDistanceWeightes[k], sumOfDistanceWeightes[k]); @@ -467,26 +455,25 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Sufficient } } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::SufficientStatistics::swapComponentStats(const size_t &idx0, const size_t &idx1) +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::SufficientStatistics::swapComponentStats(const size_t &idx0, const size_t &idx1) { - const div_t tmpIdx0 = div( idx0, VMM::VectorSize); - const div_t tmpIdx1 = div( idx1, VMM::VectorSize); + const div_t tmpIdx0 = div(idx0, VMM::VectorSize); + const div_t tmpIdx1 = div(idx1, VMM::VectorSize); std::swap(sumOfWeightedDirections[tmpIdx0.quot].x[tmpIdx0.rem], sumOfWeightedDirections[tmpIdx1.quot].x[tmpIdx1.rem]); std::swap(sumOfWeightedDirections[tmpIdx0.quot].y[tmpIdx0.rem], sumOfWeightedDirections[tmpIdx1.quot].y[tmpIdx1.rem]); std::swap(sumOfWeightedDirections[tmpIdx0.quot].z[tmpIdx0.rem], sumOfWeightedDirections[tmpIdx1.quot].z[tmpIdx1.rem]); std::swap(sumOfWeightedStats[tmpIdx0.quot][tmpIdx0.rem], sumOfWeightedStats[tmpIdx1.quot][tmpIdx1.rem]); std::swap(sumOfDistanceWeightes[tmpIdx0.quot][tmpIdx0.rem], sumOfDistanceWeightes[tmpIdx1.quot][tmpIdx1.rem]); - } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::SufficientStatistics::mergeComponentStats(const size_t &idx0, const size_t &idx1) +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::SufficientStatistics::mergeComponentStats(const size_t &idx0, const size_t &idx1) { - const div_t tmpIdx0 = div( idx0, VMM::VectorSize); - const div_t tmpIdx1 = div( idx1, VMM::VectorSize); - const div_t tmpIdx2 = div( numComponents-1, VMM::VectorSize); + const div_t tmpIdx0 = div(idx0, VMM::VectorSize); + const div_t tmpIdx1 = div(idx1, VMM::VectorSize); + const div_t tmpIdx2 = div(numComponents - 1, VMM::VectorSize); // merging the statistics of the component 0 and 1 sumOfWeightedDirections[tmpIdx0.quot].x[tmpIdx0.rem] += sumOfWeightedDirections[tmpIdx1.quot].x[tmpIdx1.rem]; @@ -501,7 +488,7 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Sufficient sumOfWeightedDirections[tmpIdx1.quot].z[tmpIdx1.rem] = sumOfWeightedDirections[tmpIdx2.quot].z[tmpIdx2.rem]; sumOfWeightedStats[tmpIdx1.quot][tmpIdx1.rem] = sumOfWeightedStats[tmpIdx2.quot][tmpIdx2.rem]; sumOfDistanceWeightes[tmpIdx1.quot][tmpIdx1.rem] = sumOfDistanceWeightes[tmpIdx2.quot][tmpIdx2.rem]; - + // reseting the statistics of the last component sumOfWeightedDirections[tmpIdx2.quot].x[tmpIdx2.rem] = 0.0f; sumOfWeightedDirections[tmpIdx2.quot].y[tmpIdx2.rem] = 0.0f; @@ -512,13 +499,13 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Sufficient numComponents--; } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::SufficientStatistics::splitComponentsStats(const size_t &idx0, const size_t &idx1, - const Vector3 &meanDirection0, const Vector3 &meanDirection1, - const float &meanCosine0, const float &meanCosine1) +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::SufficientStatistics::splitComponentsStats(const size_t &idx0, const size_t &idx1, + const Vector3 &meanDirection0, const Vector3 &meanDirection1, + const float &meanCosine0, const float &meanCosine1) { - //OPENPGL_ASSERT(meanCosine0 > 0.f && meanCosine0 <= 1.0f); - //OPENPGL_ASSERT(meanCosine1 > 0.f && meanCosine1 <= 1.0f); + // OPENPGL_ASSERT(meanCosine0 > 0.f && meanCosine0 <= 1.0f); + // OPENPGL_ASSERT(meanCosine1 > 0.f && meanCosine1 <= 1.0f); const div_t tmpI = div(idx0, static_cast(VMM::VectorSize)); const div_t tmpJ = div(idx1, static_cast(VMM::VectorSize)); @@ -549,21 +536,21 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Sufficient OPENPGL_ASSERT(!std::isnan(sumOfWeightedDirections[tmpI.quot].z[tmpI.rem]) && std::isfinite(sumOfWeightedDirections[tmpI.quot].z[tmpI.rem])); } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::SufficientStatistics::normalize( const float &_numSamples ) +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::SufficientStatistics::normalize(const float &_numSamples) { - const int cnt = (numComponents+VMM::VectorSize-1) / VMM::VectorSize; + const int cnt = (numComponents + VMM::VectorSize - 1) / VMM::VectorSize; numSamples = _numSamples; embree::vfloat sumWeightedStatsVec(0.0f); - for(int k = 0; k < cnt;k++) + for (int k = 0; k < cnt; k++) { sumWeightedStatsVec += sumOfWeightedStats[k]; } sumWeights = reduce_add(sumWeightedStatsVec); - embree::vfloat norm ( _numSamples / sumWeights ); + embree::vfloat norm(_numSamples / sumWeights); - for(int k = 0; k < cnt;k++) + for (int k = 0; k < cnt; k++) { sumOfWeightedDirections[k] *= norm; sumOfWeightedStats[k] *= norm; @@ -571,18 +558,19 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Sufficient normalized = true; } -template -typename ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::SufficientStatistics& ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::SufficientStatistics::operator+=(const typename ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::SufficientStatistics &stats) +template +typename ParallaxAwareVonMisesFisherWeightedEMFactory::SufficientStatistics & +ParallaxAwareVonMisesFisherWeightedEMFactory::SufficientStatistics::operator+=( + const typename ParallaxAwareVonMisesFisherWeightedEMFactory::SufficientStatistics &stats) { - // TODO: check for normalization - const int cnt = (numComponents+VMM::VectorSize-1) / VMM::VectorSize; + const int cnt = (numComponents + VMM::VectorSize - 1) / VMM::VectorSize; this->sumWeights += stats.sumWeights; this->numSamples += stats.numSamples; this->overallNumSamples += stats.numSamples; - for(int k = 0; k < cnt;k++) + for (int k = 0; k < cnt; k++) { this->sumOfWeightedDirections[k] += stats.sumOfWeightedDirections[k]; this->sumOfWeightedStats[k] += stats.sumOfWeightedStats[k]; @@ -592,28 +580,23 @@ typename ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Suffic return *this; } -template -bool ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::SufficientStatistics::operator==(const SufficientStatistics& b) const +template +bool ParallaxAwareVonMisesFisherWeightedEMFactory::SufficientStatistics::operator==(const SufficientStatistics &b) const { bool equal = true; - if(sumWeights != b.sumWeights || numSamples != b.numSamples || normalized != b.normalized || - overallNumSamples != b.overallNumSamples || numComponents != b.numComponents) + if (sumWeights != b.sumWeights || numSamples != b.numSamples || normalized != b.normalized || overallNumSamples != b.overallNumSamples || numComponents != b.numComponents) { equal = false; } - - for(int k = 0; k < VMM::NumVectors;k++) + + for (int k = 0; k < VMM::NumVectors; k++) { - - if( embree::any(sumOfWeightedDirections[k].x != b.sumOfWeightedDirections[k].x) || - embree::any(sumOfWeightedDirections[k].y != b.sumOfWeightedDirections[k].y) || - embree::any(sumOfWeightedDirections[k].z != b.sumOfWeightedDirections[k].z) || - embree::any(sumOfWeightedStats[k] != b.sumOfWeightedStats[k]) || + if (embree::any(sumOfWeightedDirections[k].x != b.sumOfWeightedDirections[k].x) || embree::any(sumOfWeightedDirections[k].y != b.sumOfWeightedDirections[k].y) || + embree::any(sumOfWeightedDirections[k].z != b.sumOfWeightedDirections[k].z) || embree::any(sumOfWeightedStats[k] != b.sumOfWeightedStats[k]) || embree::any(sumOfDistanceWeightes[k] != b.sumOfDistanceWeightes[k])) { equal = false; } - } return equal; } @@ -622,26 +605,26 @@ bool ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Sufficient ///////// ParallaxAwareVonMisesFisherWeightedEMFactory //////////////////////////////////////////////////////////// - -template -ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::ParallaxAwareVonMisesFisherWeightedEMFactory() +template +ParallaxAwareVonMisesFisherWeightedEMFactory::ParallaxAwareVonMisesFisherWeightedEMFactory() { _initUniformDirections(); } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory::InitUniformVMM( VMM &vmm, const int &numComponents, const float &kappa) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::InitUniformVMM(VMM &vmm, const int &numComponents, const float &kappa) const { vmm._numComponents = numComponents; const size_t nComp = vmm._numComponents; const float weight = 1.f / float(vmm._numComponents); size_t n = 0; - for ( int i = 0; i < VMM::NumVectors ; i ++) + for (int i = 0; i < VMM::NumVectors; i++) { - vmm._meanDirections[i] = _uniformDirections[nComp-1][i]; - for (int j = 0; j < VMM::VectorSize; j++){ - if ( n < nComp) + vmm._meanDirections[i] = _uniformDirections[nComp - 1][i]; + for (int j = 0; j < VMM::VectorSize; j++) + { + if (n < nComp) { vmm._kappas[i][j] = kappa; vmm._weights[i][j] = weight; @@ -660,49 +643,49 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory::InitUniform vmm._calculateNormalization(); vmm._calculateMeanCosines(); - } - -template -void ParallaxAwareVonMisesFisherWeightedEMFactory::_initUniformDirections( ) +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::_initUniformDirections() { const float gr = 1.618033988749895f; - for(uint32_t l=0; l < VMM::MaxComponents; l++){ - + for (uint32_t l = 0; l < VMM::MaxComponents; l++) + { /// distributes samples l+1 uniform samples over the sphere /// based on "Spherical Fibonacci Point Sets for Illumination Integrals" uint32_t n = 0; - for(uint32_t k=0; k < VMM::NumVectors; k++){ - - for(uint32_t i=0; i< VMM::VectorSize; i++){ - - if(n -typename ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::VMM ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::VMMfromSufficientStatistics(const SufficientStatistics &suffStats, const Configuration &cfg) const +template +typename ParallaxAwareVonMisesFisherWeightedEMFactory::VMM ParallaxAwareVonMisesFisherWeightedEMFactory::VMMfromSufficientStatistics( + const SufficientStatistics &suffStats, const Configuration &cfg) const { - SufficientStatistics previousStats; previousStats.clear(suffStats.numComponents); VMM vmm; @@ -712,24 +695,24 @@ typename ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::VMM Pa return vmm; } - -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::fitMixture(VMM &vmm, SufficientStatistics &stats, const SampleData* samples, const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::fitMixture(VMM &vmm, SufficientStatistics &stats, const SampleData *samples, const size_t numSamples, + const Configuration &cfg, FittingStatistics &fitStats) const { const size_t numComponents = cfg.initK; - //VonMisesFisherFactory< TVMMDistribution>::InitUniformVMM( vmm, numComponents, 5.0f); - this->InitUniformVMM( vmm, numComponents, cfg.initKappa); - //OPENPGL_ASSERT(vmm.isValid()); - //SufficientStatistics stats; + // VonMisesFisherFactory< TVMMDistribution>::InitUniformVMM( vmm, numComponents, 5.0f); + this->InitUniformVMM(vmm, numComponents, cfg.initKappa); + // OPENPGL_ASSERT(vmm.isValid()); + // SufficientStatistics stats; stats.clear(numComponents); stats.normalized = true; - //stats.clearAll(); + // stats.clearAll(); updateMixture(vmm, stats, samples, numSamples, cfg, fitStats); - } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::handleUnassignedSampleStats(UnassignedSamplesStatistics &unassignedStats, VMM &vmm, SufficientStatistics ¤tStats, SufficientStatistics &previousStats) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::handleUnassignedSampleStats(UnassignedSamplesStatistics &unassignedStats, VMM &vmm, + SufficientStatistics ¤tStats, SufficientStatistics &previousStats) const { const div_t tmpK = div(currentStats.numComponents, TVMMDistribution::VectorSize); currentStats.numComponents++; @@ -747,8 +730,9 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::handleUnas vmm._numComponents++; } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::updateMixture(VMM &vmm, SufficientStatistics &previousStats, const SampleData* samples, const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::updateMixture(VMM &vmm, SufficientStatistics &previousStats, const SampleData *samples, + const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) const { SufficientStatistics currentStats; // initially clear all stats @@ -759,10 +743,10 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::updateMixt float previousLogLikelihood = 0.0f; float inv_previousLogLikelihood = 1.0f; UnassignedSamplesStatistics unassignedStats; - while ( !converged && currentEMIteration < cfg.maxEMIterrations ) + while (!converged && currentEMIteration < cfg.maxEMIterrations) { - float logLikelihood = weightedExpectationStep( vmm, currentStats, unassignedStats, samples, numSamples); - if(unassignedStats.sumOfUnassignedWeights > 0.0f && currentStats.numComponents < TVMMDistribution::MaxComponents) + float logLikelihood = weightedExpectationStep(vmm, currentStats, unassignedStats, samples, numSamples); + if (unassignedStats.sumOfUnassignedWeights > 0.0f && currentStats.numComponents < TVMMDistribution::MaxComponents) { handleUnassignedSampleStats(unassignedStats, vmm, currentStats, previousStats); } @@ -770,18 +754,19 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::updateMixt OPENPGL_ASSERT(!currentStats.isNormalized()); currentStats.normalize(currentStats.numSamples); OPENPGL_ASSERT(currentStats.isValid()); - weightedMaximumAPosteriorStep( vmm, currentStats, previousStats, cfg); + weightedMaximumAPosteriorStep(vmm, currentStats, previousStats, cfg); currentEMIteration++; // TODO: Add convergence check - if (currentEMIteration >1) + if (currentEMIteration > 1) { float relLogLikelihoodDifference = std::fabs(logLikelihood - previousLogLikelihood) * inv_previousLogLikelihood; - if(relLogLikelihoodDifference < cfg.convergenceThreshold) + if (relLogLikelihoodDifference < cfg.convergenceThreshold) { converged = true; } - //std::cout << "logLikelihood:" << logLikelihood << "\t previousLogLikelihood: "<< previousLogLikelihood << "\t relLogLikelihoodDifference: " << relLogLikelihoodDifference << std::endl; + // std::cout << "logLikelihood:" << logLikelihood << "\t previousLogLikelihood: "<< previousLogLikelihood << "\t relLogLikelihoodDifference: " << + // relLogLikelihoodDifference << std::endl; previousLogLikelihood = logLikelihood; inv_previousLogLikelihood = 1.0f / std::fabs(logLikelihood); } @@ -791,11 +776,13 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::updateMixt fitStats.numSamples = numSamples; fitStats.numIterations = currentEMIteration; fitStats.summedWeightedLogLikelihood = previousLogLikelihood; - //td::cout << "converged:" << currentEMIteration << std::endl; + // td::cout << "converged:" << currentEMIteration << std::endl; } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::partialUpdateMixture(VMM &vmm, PartialFittingMask &mask, SufficientStatistics &previousStats, const SampleData* samples, const size_t numSamples, const Configuration &cfg, FittingStatistics &fitStats) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::partialUpdateMixture(VMM &vmm, PartialFittingMask &mask, SufficientStatistics &previousStats, + const SampleData *samples, const size_t numSamples, const Configuration &cfg, + FittingStatistics &fitStats) const { SufficientStatistics currentStats; // initially clear all stats @@ -807,13 +794,13 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::partialUpd float inv_previousLogLikelihood = 1.0f; UnassignedSamplesStatistics unassignedStats; - while ( !converged && currentEMIteration < cfg.maxEMIterrations ) + while (!converged && currentEMIteration < cfg.maxEMIterrations) { - float logLikelihood = weightedExpectationStep( vmm, currentStats, unassignedStats, samples, numSamples); - if(unassignedStats.sumOfUnassignedWeights > 0.0f && currentStats.numComponents < TVMMDistribution::MaxComponents) + float logLikelihood = weightedExpectationStep(vmm, currentStats, unassignedStats, samples, numSamples); + if (unassignedStats.sumOfUnassignedWeights > 0.0f && currentStats.numComponents < TVMMDistribution::MaxComponents) { handleUnassignedSampleStats(unassignedStats, vmm, currentStats, previousStats); - mask.setToTrue(vmm._numComponents-1); + mask.setToTrue(vmm._numComponents - 1); } OPENPGL_ASSERT(currentStats.isValid()); @@ -821,17 +808,18 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::partialUpd currentStats.normalize(currentStats.numSamples); OPENPGL_ASSERT(currentStats.isValid()); - partialWeightedMaximumAPosteriorStep( vmm, mask, currentStats, previousStats, cfg); + partialWeightedMaximumAPosteriorStep(vmm, mask, currentStats, previousStats, cfg); currentEMIteration++; // TODO: Add convergence check - if (currentEMIteration >1) + if (currentEMIteration > 1) { float relLogLikelihoodDifference = std::fabs(logLikelihood - previousLogLikelihood) * inv_previousLogLikelihood; - if(relLogLikelihoodDifference < cfg.convergenceThreshold) + if (relLogLikelihoodDifference < cfg.convergenceThreshold) { converged = true; } - //std::cout << "logLikelihood:" << logLikelihood << "\t previousLogLikelihood: "<< previousLogLikelihood << "\t relLogLikelihoodDifference: " << relLogLikelihoodDifference << std::endl; + // std::cout << "logLikelihood:" << logLikelihood << "\t previousLogLikelihood: "<< previousLogLikelihood << "\t relLogLikelihoodDifference: " << + // relLogLikelihoodDifference << std::endl; previousLogLikelihood = logLikelihood; inv_previousLogLikelihood = 1.0f / std::fabs(logLikelihood); } @@ -841,37 +829,34 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::partialUpd fitStats.numSamples = numSamples; fitStats.numIterations = currentEMIteration; fitStats.summedWeightedLogLikelihood = previousLogLikelihood; - //std::cout << "converged:" << currentEMIteration << std::endl; + // std::cout << "converged:" << currentEMIteration << std::endl; } -template -float ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::weightedExpectationStep(VMM &vmm, - SufficientStatistics &stats, - UnassignedSamplesStatistics &unassignedStats, - const SampleData* samples, - const size_t numSamples) const +template +float ParallaxAwareVonMisesFisherWeightedEMFactory::weightedExpectationStep(VMM &vmm, SufficientStatistics &stats, UnassignedSamplesStatistics &unassignedStats, + const SampleData *samples, const size_t numSamples) const { unassignedStats.clear(); stats.clear(vmm._numComponents); stats.numComponents = vmm._numComponents; stats.numSamples = numSamples; - const int cnt = (stats.numComponents+VMM::VectorSize-1) / VMM::VectorSize; + const int cnt = (stats.numComponents + VMM::VectorSize - 1) / VMM::VectorSize; - float summedWeightedLogLikelihood {0.f}; + float summedWeightedLogLikelihood{0.f}; typename VMM::SoftAssignment softAssign; - for (size_t n = 0; n < numSamples; n++ ) + for (size_t n = 0; n < numSamples; n++) { const SampleData sampleData = samples[n]; const embree::vfloat sampleWeight = sampleData.weight; pgl_vec3f direction = sampleData.direction; const Vector3 sampleDirection(direction.x, direction.y, direction.z); - const embree::Vec3< embree::vfloat > sampleDirectionSIMD( sampleDirection ); + const embree::Vec3 > sampleDirectionSIMD(sampleDirection); // check if the samples is covered by any of the components - if ( !vmm.softAssignment( sampleDirection, softAssign) ) + if (!vmm.softAssignment(sampleDirection, softAssign)) { unassignedStats.sumOfUnassignedWeights += sampleData.weight; unassignedStats.sumUnassignedWeightedDirections += sampleDirection * sampleData.weight; @@ -881,91 +866,85 @@ float ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::weightedE continue; } - summedWeightedLogLikelihood += sampleData.weight * embree::log( softAssign.pdf ); + summedWeightedLogLikelihood += sampleData.weight * embree::log(softAssign.pdf); - for (size_t k =0; k < cnt; k++) + for (size_t k = 0; k < cnt; k++) { stats.sumOfWeightedDirections[k] += sampleDirectionSIMD * softAssign.assignments[k] * sampleWeight; stats.sumOfWeightedStats[k] += softAssign.assignments[k] * sampleWeight; } - } return summedWeightedLogLikelihood; } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::estimateMAPWeights( VMM &vmm, - const SufficientStatistics ¤tStats, - const SufficientStatistics &previousStats, - const float &_weightPrior ) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::estimateMAPWeights(VMM &vmm, const SufficientStatistics ¤tStats, + const SufficientStatistics &previousStats, const float &_weightPrior) const { - const int cnt = (vmm._numComponents+VMM::VectorSize-1) / VMM::VectorSize; + const int cnt = (vmm._numComponents + VMM::VectorSize - 1) / VMM::VectorSize; const size_t numComponents = vmm._numComponents; const embree::vfloat weightPrior(_weightPrior); const embree::vfloat numSamples = currentStats.numSamples + previousStats.numSamples; - //const vfloat numSamples = currentStats.numSamples + previousStats.overallNumSamples; + // const vfloat numSamples = currentStats.numSamples + previousStats.overallNumSamples; - for ( size_t k = 0; k < cnt; k ++ ) + for (size_t k = 0; k < cnt; k++) { //_sumWeights += currentStats.sumOfWeightedStats[k]; - embree::vfloat weight = ( currentStats.sumOfWeightedStats[k] + previousStats.sumOfWeightedStats[k] ) ; - weight = ( weightPrior + ( weight ) ) / (( weightPrior * numComponents ) + numSamples ); - //vfloat weight = ( currentStats.sumOfWeightedStats[k]/* + previousStats.sumOfWeightedStats[k]*/ ) / ( sumWeights ); - //weight = ( weightPrior + ( weight * numSamples ) ) / (( weightPrior * numComponents ) + numSamples ); + embree::vfloat weight = (currentStats.sumOfWeightedStats[k] + previousStats.sumOfWeightedStats[k]); + weight = (weightPrior + (weight)) / ((weightPrior * numComponents) + numSamples); + // vfloat weight = ( currentStats.sumOfWeightedStats[k]/* + previousStats.sumOfWeightedStats[k]*/ ) / ( sumWeights ); + // weight = ( weightPrior + ( weight * numSamples ) ) / (( weightPrior * numComponents ) + numSamples ); vmm._weights[k] = weight; } // TODO: find better more efficient way - if ( vmm._numComponents % VMM::VectorSize > 0 ) + if (vmm._numComponents % VMM::VectorSize > 0) { - for (size_t i = vmm._numComponents % VMM::VectorSize; i < VMM::VectorSize; i++ ) - { - vmm._weights[cnt-1][i] = 0.0f; - } + for (size_t i = vmm._numComponents % VMM::VectorSize; i < VMM::VectorSize; i++) + { + vmm._weights[cnt - 1][i] = 0.0f; + } } } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::estimateMAPMeanDirectionAndConcentration( VMM &vmm, - const SufficientStatistics ¤tStats, - const SufficientStatistics &previousStats , - const Configuration &cfg) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::estimateMAPMeanDirectionAndConcentration(VMM &vmm, const SufficientStatistics ¤tStats, + const SufficientStatistics &previousStats, + const Configuration &cfg) const { const embree::vfloat currentNumSamples = currentStats.numSamples; const embree::vfloat previousNumSamples = previousStats.numSamples; const embree::vfloat numSamples = currentNumSamples + previousNumSamples; const embree::vfloat overallNumSamples = currentStats.numSamples + previousStats.overallNumSamples; - const embree::vfloat currentEstimationWeight = currentNumSamples / numSamples; const embree::vfloat previousEstimationWeight = 1.0f - currentEstimationWeight; const embree::vfloat meanCosinePrior = cfg.meanCosinePrior; const embree::vfloat meanCosinePriorStrength = cfg.meanCosinePriorStrength; const embree::vfloat maxMeanCosine = cfg.maxMeanCosine; - const int cnt = (vmm._numComponents+VMM::VectorSize-1) / VMM::VectorSize; + const int cnt = (vmm._numComponents + VMM::VectorSize - 1) / VMM::VectorSize; const int rem = vmm._numComponents % VMM::VectorSize; - for (size_t k = 0; k < cnt; k ++) + for (size_t k = 0; k < cnt; k++) { - //const vfloat partialNumSamples = vmm._weights[k] * numSamples; + // const vfloat partialNumSamples = vmm._weights[k] * numSamples; const embree::vfloat partialNumSamples = vmm._weights[k] * overallNumSamples; - embree::Vec3< embree::vfloat > currentMeanDirection; + embree::Vec3 > currentMeanDirection; currentMeanDirection.x = select(currentStats.sumOfWeightedStats[k] > 0.0f, currentStats.sumOfWeightedDirections[k].x / currentStats.sumOfWeightedStats[k], 0.0f); currentMeanDirection.y = select(currentStats.sumOfWeightedStats[k] > 0.0f, currentStats.sumOfWeightedDirections[k].y / currentStats.sumOfWeightedStats[k], 0.0f); currentMeanDirection.z = select(currentStats.sumOfWeightedStats[k] > 0.0f, currentStats.sumOfWeightedDirections[k].z / currentStats.sumOfWeightedStats[k], 0.0f); // TODO: find a better design to precompute the previousMeanDirection - embree::Vec3< embree::vfloat > previousMeanDirection; + embree::Vec3 > previousMeanDirection; previousMeanDirection.x = select(previousStats.sumOfWeightedStats[k] > 0.0f, previousStats.sumOfWeightedDirections[k].x / previousStats.sumOfWeightedStats[k], 0.0f); previousMeanDirection.y = select(previousStats.sumOfWeightedStats[k] > 0.0f, previousStats.sumOfWeightedDirections[k].y / previousStats.sumOfWeightedStats[k], 0.0f); previousMeanDirection.z = select(previousStats.sumOfWeightedStats[k] > 0.0f, previousStats.sumOfWeightedDirections[k].z / previousStats.sumOfWeightedStats[k], 0.0f); - embree::Vec3< embree::vfloat > meanDirection = currentMeanDirection * currentEstimationWeight - + previousMeanDirection * previousEstimationWeight; + embree::Vec3 > meanDirection = currentMeanDirection * currentEstimationWeight + previousMeanDirection * previousEstimationWeight; embree::vfloat meanCosine = length(meanDirection); @@ -973,186 +952,174 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::estimateMA vmm._meanDirections[k].y = select(meanCosine > 0.0f, meanDirection.y / meanCosine, vmm._meanDirections[k].y); vmm._meanDirections[k].z = select(meanCosine > 0.0f, meanDirection.z / meanCosine, vmm._meanDirections[k].z); - meanCosine = ( meanCosinePrior * meanCosinePriorStrength + meanCosine * partialNumSamples ) / ( meanCosinePriorStrength + partialNumSamples ); + meanCosine = (meanCosinePrior * meanCosinePriorStrength + meanCosine * partialNumSamples) / (meanCosinePriorStrength + partialNumSamples); - meanCosine = embree::min( maxMeanCosine, meanCosine ); + meanCosine = embree::min(maxMeanCosine, meanCosine); vmm._meanCosines[k] = meanCosine; - vmm._kappas[k] = MeanCosineToKappa< embree::vfloat >( meanCosine ); + vmm._kappas[k] = MeanCosineToKappa >(meanCosine); } // TODO: find better more efficient way - if ( rem > 0 ) + if (rem > 0) { - for ( size_t i = rem; i < VMM::VectorSize; i++) + for (size_t i = rem; i < VMM::VectorSize; i++) { - vmm._meanDirections[cnt-1].x[i] = 0.0f; - vmm._meanDirections[cnt-1].y[i] = 0.0f; - vmm._meanDirections[cnt-1].z[i] = 1.0f; + vmm._meanDirections[cnt - 1].x[i] = 0.0f; + vmm._meanDirections[cnt - 1].y[i] = 0.0f; + vmm._meanDirections[cnt - 1].z[i] = 1.0f; - vmm._meanCosines[cnt-1][i] = 0.0f; - vmm._kappas[cnt-1][i] = 0.0f; + vmm._meanCosines[cnt - 1][i] = 0.0f; + vmm._kappas[cnt - 1][i] = 0.0f; - vmm._normalizations[cnt-1][i] = ONE_OVER_FOUR_PI; - vmm._eMinus2Kappa[cnt-1][i] = 1.0f; + vmm._normalizations[cnt - 1][i] = ONE_OVER_FOUR_PI; + vmm._eMinus2Kappa[cnt - 1][i] = 1.0f; } } vmm._calculateNormalization(); } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::weightedMaximumAPosteriorStep(VMM &vmm, - const SufficientStatistics ¤tStats, - const SufficientStatistics &previousStats, - const Configuration &cfg) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::weightedMaximumAPosteriorStep(VMM &vmm, const SufficientStatistics ¤tStats, + const SufficientStatistics &previousStats, const Configuration &cfg) const { // Estimating components weights - estimateMAPWeights( vmm, currentStats, previousStats, cfg.weightPrior ); + estimateMAPWeights(vmm, currentStats, previousStats, cfg.weightPrior); // Estimating mean and concentration - estimateMAPMeanDirectionAndConcentration( vmm, currentStats, previousStats, cfg); + estimateMAPMeanDirectionAndConcentration(vmm, currentStats, previousStats, cfg); } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::partialWeightedMaximumAPosteriorStep(VMM &vmm, - const PartialFittingMask &mask, - SufficientStatistics ¤tStats, - SufficientStatistics &previousStats, - const Configuration &cfg) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::partialWeightedMaximumAPosteriorStep(VMM &vmm, const PartialFittingMask &mask, + SufficientStatistics ¤tStats, SufficientStatistics &previousStats, + const Configuration &cfg) const { // Estimating components weights - estimatePartialMAPWeights( vmm, mask, currentStats, previousStats, cfg.weightPrior ); + estimatePartialMAPWeights(vmm, mask, currentStats, previousStats, cfg.weightPrior); // Estimating mean and concentration - estimatePartialMAPMeanDirectionAndConcentration( vmm, mask, currentStats, previousStats, cfg); + estimatePartialMAPMeanDirectionAndConcentration(vmm, mask, currentStats, previousStats, cfg); } - -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::estimatePartialMAPWeights( VMM &vmm, - const PartialFittingMask &mask, - SufficientStatistics ¤tStats, - SufficientStatistics &previousStats, - const float &_weightPrior ) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::estimatePartialMAPWeights(VMM &vmm, const PartialFittingMask &mask, SufficientStatistics ¤tStats, + SufficientStatistics &previousStats, const float &_weightPrior) const { const embree::vfloat zeros(0.0f); - const int cnt = (vmm._numComponents+VMM::VectorSize-1) / VMM::VectorSize; + const int cnt = (vmm._numComponents + VMM::VectorSize - 1) / VMM::VectorSize; const size_t numComponents = vmm._numComponents; const embree::vfloat weightPrior(_weightPrior); const embree::vfloat numSamples = currentStats.numSamples + previousStats.numSamples; - //const vfloat numSamples = currentStats.numSamples + previousStats.overallNumSamples; + // const vfloat numSamples = currentStats.numSamples + previousStats.overallNumSamples; embree::vfloat sumWeights(0.0f); embree::vfloat sumPartialWeights(0.0f); - for ( size_t k = 0; k < cnt; k ++ ) + for (size_t k = 0; k < cnt; k++) { //_sumWeights += currentStats.sumOfWeightedStats[k]; - embree::vfloat weight = ( currentStats.sumOfWeightedStats[k] + previousStats.sumOfWeightedStats[k] ) ; - weight = ( weightPrior + ( weight ) ) / (( weightPrior * numComponents ) + numSamples ); - //vfloat weight = ( currentStats.sumOfWeightedStats[k]/* + previousStats.sumOfWeightedStats[k]*/ ) / ( sumWeights ); - //weight = ( weightPrior + ( weight * numSamples ) ) / (( weightPrior * numComponents ) + numSamples ); + embree::vfloat weight = (currentStats.sumOfWeightedStats[k] + previousStats.sumOfWeightedStats[k]); + weight = (weightPrior + (weight)) / ((weightPrior * numComponents) + numSamples); + // vfloat weight = ( currentStats.sumOfWeightedStats[k]/* + previousStats.sumOfWeightedStats[k]*/ ) / ( sumWeights ); + // weight = ( weightPrior + ( weight * numSamples ) ) / (( weightPrior * numComponents ) + numSamples ); sumPartialWeights += select(mask.mask[k], weight, zeros); sumWeights += select(mask.mask[k], zeros, vmm._weights[k]); - vmm._weights[k] =select(mask.mask[k], weight, vmm._weights[k]); + vmm._weights[k] = select(mask.mask[k], weight, vmm._weights[k]); } embree::vfloat inv_sumPartialWeights = 1.0f / reduce_add(sumPartialWeights); inv_sumPartialWeights *= 1.0f - reduce_add(sumWeights); - for ( size_t k = 0; k < cnt; k ++ ) + for (size_t k = 0; k < cnt; k++) { - vmm._weights[k] =select(mask.mask[k], vmm._weights[k] * inv_sumPartialWeights, vmm._weights[k]); + vmm._weights[k] = select(mask.mask[k], vmm._weights[k] * inv_sumPartialWeights, vmm._weights[k]); } // TODO: find better more efficient way - if ( vmm._numComponents % VMM::VectorSize > 0 ) + if (vmm._numComponents % VMM::VectorSize > 0) { - for (size_t i = vmm._numComponents % VMM::VectorSize; i < VMM::VectorSize; i++ ) - { - vmm._weights[cnt-1][i] = 0.0f; - } + for (size_t i = vmm._numComponents % VMM::VectorSize; i < VMM::VectorSize; i++) + { + vmm._weights[cnt - 1][i] = 0.0f; + } } } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::estimatePartialMAPMeanDirectionAndConcentration( VMM &vmm, - const PartialFittingMask &mask, - SufficientStatistics ¤tStats, - SufficientStatistics &previousStats , - const Configuration &cfg) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::estimatePartialMAPMeanDirectionAndConcentration(VMM &vmm, const PartialFittingMask &mask, + SufficientStatistics ¤tStats, + SufficientStatistics &previousStats, + const Configuration &cfg) const { const embree::vfloat currentNumSamples = currentStats.numSamples; const embree::vfloat previousNumSamples = previousStats.numSamples; const embree::vfloat numSamples = currentNumSamples + previousNumSamples; const embree::vfloat overallNumSamples = currentStats.numSamples + previousStats.overallNumSamples; - const embree::vfloat currentEstimationWeight = currentNumSamples / numSamples; const embree::vfloat previousEstimationWeight = 1.0f - currentEstimationWeight; const embree::vfloat meanCosinePrior = cfg.meanCosinePrior; const embree::vfloat meanCosinePriorStrength = cfg.meanCosinePriorStrength; const embree::vfloat maxMeanCosine = cfg.maxMeanCosine; - const int cnt = (vmm._numComponents+VMM::VectorSize-1) / VMM::VectorSize; + const int cnt = (vmm._numComponents + VMM::VectorSize - 1) / VMM::VectorSize; const int rem = vmm._numComponents % VMM::VectorSize; - for (size_t k = 0; k < cnt; k ++) + for (size_t k = 0; k < cnt; k++) { - //const vfloat partialNumSamples = vmm._weights[k] * numSamples; + // const vfloat partialNumSamples = vmm._weights[k] * numSamples; const embree::vfloat partialNumSamples = vmm._weights[k] * overallNumSamples; - embree::Vec3< embree::vfloat > currentMeanDirection; + embree::Vec3 > currentMeanDirection; currentMeanDirection.x = select(currentStats.sumOfWeightedStats[k] > 0.0f, currentStats.sumOfWeightedDirections[k].x / currentStats.sumOfWeightedStats[k], 0.0f); currentMeanDirection.y = select(currentStats.sumOfWeightedStats[k] > 0.0f, currentStats.sumOfWeightedDirections[k].y / currentStats.sumOfWeightedStats[k], 0.0f); currentMeanDirection.z = select(currentStats.sumOfWeightedStats[k] > 0.0f, currentStats.sumOfWeightedDirections[k].z / currentStats.sumOfWeightedStats[k], 0.0f); // TODO: find a better design to precompute the previousMeanDirection - embree::Vec3< embree::vfloat > previousMeanDirection; + embree::Vec3 > previousMeanDirection; previousMeanDirection.x = select(previousStats.sumOfWeightedStats[k] > 0.0f, previousStats.sumOfWeightedDirections[k].x / previousStats.sumOfWeightedStats[k], 0.0f); previousMeanDirection.y = select(previousStats.sumOfWeightedStats[k] > 0.0f, previousStats.sumOfWeightedDirections[k].y / previousStats.sumOfWeightedStats[k], 0.0f); previousMeanDirection.z = select(previousStats.sumOfWeightedStats[k] > 0.0f, previousStats.sumOfWeightedDirections[k].z / previousStats.sumOfWeightedStats[k], 0.0f); - embree::Vec3< embree::vfloat > meanDirection = currentMeanDirection * currentEstimationWeight - + previousMeanDirection * previousEstimationWeight; + embree::Vec3 > meanDirection = currentMeanDirection * currentEstimationWeight + previousMeanDirection * previousEstimationWeight; embree::vfloat meanCosine = embree::length(meanDirection); - vmm._meanDirections[k].x = select( mask.mask[k], select(meanCosine > 0.0f, meanDirection.x / meanCosine, vmm._meanDirections[k].x) , vmm._meanDirections[k].x); - vmm._meanDirections[k].y = select( mask.mask[k], select(meanCosine > 0.0f, meanDirection.y / meanCosine, vmm._meanDirections[k].y), vmm._meanDirections[k].y); - vmm._meanDirections[k].z = select( mask.mask[k], select(meanCosine > 0.0f, meanDirection.z / meanCosine, vmm._meanDirections[k].z), vmm._meanDirections[k].z); + vmm._meanDirections[k].x = select(mask.mask[k], select(meanCosine > 0.0f, meanDirection.x / meanCosine, vmm._meanDirections[k].x), vmm._meanDirections[k].x); + vmm._meanDirections[k].y = select(mask.mask[k], select(meanCosine > 0.0f, meanDirection.y / meanCosine, vmm._meanDirections[k].y), vmm._meanDirections[k].y); + vmm._meanDirections[k].z = select(mask.mask[k], select(meanCosine > 0.0f, meanDirection.z / meanCosine, vmm._meanDirections[k].z), vmm._meanDirections[k].z); - meanCosine = ( meanCosinePrior * meanCosinePriorStrength + meanCosine * partialNumSamples ) / ( meanCosinePriorStrength + partialNumSamples ); + meanCosine = (meanCosinePrior * meanCosinePriorStrength + meanCosine * partialNumSamples) / (meanCosinePriorStrength + partialNumSamples); - meanCosine = embree::min( maxMeanCosine, meanCosine ); - vmm._meanCosines[k] = select( mask.mask[k], meanCosine, vmm._meanCosines[k]); - vmm._kappas[k] = select( mask.mask[k], MeanCosineToKappa< embree::vfloat >( meanCosine ), vmm._kappas[k]); + meanCosine = embree::min(maxMeanCosine, meanCosine); + vmm._meanCosines[k] = select(mask.mask[k], meanCosine, vmm._meanCosines[k]); + vmm._kappas[k] = select(mask.mask[k], MeanCosineToKappa >(meanCosine), vmm._kappas[k]); } // TODO: find better more efficient way - if ( rem > 0 ) + if (rem > 0) { - for ( size_t i = rem; i < VMM::VectorSize; i++) + for (size_t i = rem; i < VMM::VectorSize; i++) { - vmm._meanDirections[cnt-1].x[i] = 0.0f; - vmm._meanDirections[cnt-1].y[i] = 0.0f; - vmm._meanDirections[cnt-1].z[i] = 1.0f; + vmm._meanDirections[cnt - 1].x[i] = 0.0f; + vmm._meanDirections[cnt - 1].y[i] = 0.0f; + vmm._meanDirections[cnt - 1].z[i] = 1.0f; - vmm._meanCosines[cnt-1][i] = 0.0f; - vmm._kappas[cnt-1][i] = 0.0f; + vmm._meanCosines[cnt - 1][i] = 0.0f; + vmm._kappas[cnt - 1][i] = 0.0f; } } vmm._calculateNormalization(); } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::reprojectSample(openpgl::SampleData &sample, const openpgl::Point3 &pivotPoint, const float minDistance) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::reprojectSample(openpgl::SampleData &sample, const openpgl::Point3 &pivotPoint, const float minDistance) const { - if (std::isinf(sample.distance)) { sample.position.x = pivotPoint[0]; @@ -1182,10 +1149,11 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::reprojectS sample.direction = qdirection; } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::prepareSamples(SampleData* samples, const size_t numSamples, const SampleStatistics &sampleStatistics, const Configuration &cfg) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::prepareSamples(SampleData *samples, const size_t numSamples, const SampleStatistics &sampleStatistics, + const Configuration &cfg) const { - if(TVMMDistribution::ParallaxCompensation) + if (TVMMDistribution::ParallaxCompensation) { openpgl::Vector3 sampleVariance = sampleStatistics.getVariance(); float minDistance = length(sampleVariance); @@ -1197,8 +1165,9 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::prepareSam } } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::initComponentDistances (VMM &vmm, SufficientStatistics &sufficientStats, const SampleData* samples, const size_t numSamples) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::initComponentDistances(VMM &vmm, SufficientStatistics &sufficientStats, const SampleData *samples, + const size_t numSamples) const { OPENPGL_ASSERT(vmm.getNumComponents() == sufficientStats.getNumComponents()); @@ -1207,7 +1176,7 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::initCompon const embree::vfloat zeros(0.0f); - const int cnt = (vmm._numComponents+VMM::VectorSize-1) / VMM::VectorSize; + const int cnt = (vmm._numComponents + VMM::VectorSize - 1) / VMM::VectorSize; const int rem = vmm._numComponents % VMM::VectorSize; for (size_t k = 0; k < cnt; k++) @@ -1232,7 +1201,7 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::initCompon { for (size_t k = 0; k < cnt; k++) { - weights = samples[n].weight * softAssign.assignments[k] * ( (softAssign.assignments[k] * softAssign.pdf) / vmm._weights[k]); + weights = samples[n].weight * softAssign.assignments[k] * ((softAssign.assignments[k] * softAssign.pdf) / vmm._weights[k]); batchDistances[k] += weights * sampleDistance; batchSumWeights[k] += weights; } @@ -1250,18 +1219,19 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::initCompon #endif } - if ( rem > 0 ) + if (rem > 0) { - for ( size_t i = rem; i < VMM::VectorSize; i++) + for (size_t i = rem; i < VMM::VectorSize; i++) { - vmm._distances[cnt-1][i] = 0.0f; - sufficientStats.sumOfDistanceWeightes[cnt-1][i] = 0.0f; + vmm._distances[cnt - 1][i] = 0.0f; + sufficientStats.sumOfDistanceWeightes[cnt - 1][i] = 0.0f; } } } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::updateComponentDistances (VMM &vmm, SufficientStatistics &sufficientStats, const SampleData* samples, const size_t numSamples) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::updateComponentDistances(VMM &vmm, SufficientStatistics &sufficientStats, const SampleData *samples, + const size_t numSamples) const { OPENPGL_ASSERT(vmm.getNumComponents() == sufficientStats.getNumComponents()); @@ -1269,7 +1239,7 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::updateComp embree::vfloat batchSumWeights[VMM::NumVectors]; const embree::vfloat zeros(0.0f); - const int cnt = (vmm._numComponents+VMM::VectorSize-1) / VMM::VectorSize; + const int cnt = (vmm._numComponents + VMM::VectorSize - 1) / VMM::VectorSize; const int rem = vmm._numComponents % VMM::VectorSize; for (size_t k = 0; k < cnt; k++) @@ -1296,7 +1266,7 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::updateComp { for (size_t k = 0; k < cnt; k++) { - weights = samples[n].weight * softAssign.assignments[k] * ( (softAssign.assignments[k] * softAssign.pdf) / vmm._weights[k]); + weights = samples[n].weight * softAssign.assignments[k] * ((softAssign.assignments[k] * softAssign.pdf) / vmm._weights[k]); batchDistances[k] += weights * sampleDistance; batchSumWeights[k] += weights; } @@ -1306,9 +1276,9 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::updateComp for (size_t k = 0; k < cnt; k++) { #ifdef USE_HARMONIC_MEAN - //embree::vfloat sumInverseDistances = (sufficientStats.sumOfDistanceWeightes[k] / vmm._distances[k]) + batchDistances[k]; + // embree::vfloat sumInverseDistances = (sufficientStats.sumOfDistanceWeightes[k] / vmm._distances[k]) + batchDistances[k]; embree::vfloat sumInverseDistances = batchDistances[k]; - sumInverseDistances += select( vmm._distances[k] > 0.0f , (sufficientStats.sumOfDistanceWeightes[k] / vmm._distances[k]) , embree::vfloat(0.0f)); + sumInverseDistances += select(vmm._distances[k] > 0.0f, (sufficientStats.sumOfDistanceWeightes[k] / vmm._distances[k]), embree::vfloat(0.0f)); sufficientStats.sumOfDistanceWeightes[k] += batchSumWeights[k]; vmm._distances[k] = sufficientStats.sumOfDistanceWeightes[k] / sumInverseDistances; #else @@ -1318,35 +1288,35 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::updateComp #endif } - if ( rem > 0 ) + if (rem > 0) { - for ( size_t i = rem; i < VMM::VectorSize; i++) + for (size_t i = rem; i < VMM::VectorSize; i++) { - vmm._distances[cnt-1][i] = 0.0f; - sufficientStats.sumOfDistanceWeightes[cnt-1][i] = 0.0f; + vmm._distances[cnt - 1][i] = 0.0f; + sufficientStats.sumOfDistanceWeightes[cnt - 1][i] = 0.0f; } } - } #ifdef OPENPGL_RADIANCE_CACHES -template -void ParallaxAwareVonMisesFisherWeightedEMFactory::updateFluenceEstimate(VMM &vmm, const SampleData* samples, const size_t numSamples, const size_t numZeroValueSamples, const SampleStatistics &sampleStatistics) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::updateFluenceEstimate(VMM &vmm, const SampleData *samples, const size_t numSamples, + const size_t numZeroValueSamples, const SampleStatistics &sampleStatistics) const { -#ifdef MC_ESTIMATE_INCOMING_RADIANCE //calcualting fluence and the RGB per lob estiamtions using the MC samples - if(numSamples == 0) +#ifdef MC_ESTIMATE_INCOMING_RADIANCE // calcualting fluence and the RGB per lob estiamtions using the MC samples + if (numSamples == 0) { return; } - - const int cnt = (vmm._numComponents+VMM::VectorSize-1) / VMM::VectorSize; + + const int cnt = (vmm._numComponents + VMM::VectorSize - 1) / VMM::VectorSize; const int rem = vmm._numComponents % VMM::VectorSize; const embree::vfloat zeros(0.0f); - //float sumFluence {0.f}; - Vector3 sumFluenceRGB {0.f, 0.f, 0.f}; - Vector3 sumFluenceRGBWithMIS {0.f, 0.f, 0.f}; + // float sumFluence {0.f}; + Vector3 sumFluenceRGB{0.f, 0.f, 0.f}; + Vector3 sumFluenceRGBWithMIS{0.f, 0.f, 0.f}; embree::Vec3 > sumFluenceRGBWeights[VMM::NumVectors]; embree::Vec3 > sumFluenceRGBWeightsWithMIS[VMM::NumVectors]; @@ -1364,14 +1334,14 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory::updateFluen } for (size_t n = 0; n < numSamples; n++) - { - //sumFluence += samples[n].weight; + { + // sumFluence += samples[n].weight; pgl_vec3f direction = samples[n].direction; const Vector3 sampleDirection(direction.x, direction.y, direction.z); pgl_vec3f color = samples[n].radianceIn; Vector3 radianceIn(color.x, color.y, color.z); radianceIn /= samples[n].pdf; - + Vector3 radianceInNoMIS = isDirectLight(samples[n]) ? radianceIn / samples[n].radianceInMISWeight : radianceIn; sumFluenceRGB += radianceInNoMIS; @@ -1394,17 +1364,17 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory::updateFluen const float oldNumFluenceSamples = vmm._numFluenceSamples; const float newNumFluenceSamples = (oldNumFluenceSamples + float(numSamples + numZeroValueSamples)); - if ( rem > 0 ) + if (rem > 0) { - for ( size_t i = rem; i < VMM::VectorSize; i++) + for (size_t i = rem; i < VMM::VectorSize; i++) { - sumFluenceRGBWeights[cnt-1].x[i] = 0.0f; - sumFluenceRGBWeights[cnt-1].y[i] = 0.0f; - sumFluenceRGBWeights[cnt-1].z[i] = 0.0f; + sumFluenceRGBWeights[cnt - 1].x[i] = 0.0f; + sumFluenceRGBWeights[cnt - 1].y[i] = 0.0f; + sumFluenceRGBWeights[cnt - 1].z[i] = 0.0f; - sumFluenceRGBWeightsWithMIS[cnt-1].x[i] = 0.0f; - sumFluenceRGBWeightsWithMIS[cnt-1].y[i] = 0.0f; - sumFluenceRGBWeightsWithMIS[cnt-1].z[i] = 0.0f; + sumFluenceRGBWeightsWithMIS[cnt - 1].x[i] = 0.0f; + sumFluenceRGBWeightsWithMIS[cnt - 1].y[i] = 0.0f; + sumFluenceRGBWeightsWithMIS[cnt - 1].z[i] = 0.0f; } } @@ -1422,14 +1392,15 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory::updateFluen vmm._fluenceRGB = ((vmm._fluenceRGB * oldNumFluenceSamples) + sumFluenceRGB) / newNumFluenceSamples; vmm._fluenceRGBWithMIS = ((vmm._fluenceRGBWithMIS * oldNumFluenceSamples) + sumFluenceRGBWithMIS) / newNumFluenceSamples; - //vmm._fluence = ((vmm._fluence * oldNumFluenceSamples) + sumFluence) / newNumFluenceSamples; + // vmm._fluence = ((vmm._fluence * oldNumFluenceSamples) + sumFluence) / newNumFluenceSamples; vmm._numFluenceSamples = newNumFluenceSamples; -#else //calcualting fluence and the RGB per lob estiamtions using the soft assigns counter to average the incoming radiance per lobe (getting rid of the PDF dependency) TODO: maybe drop this code +#else // calcualting fluence and the RGB per lob estiamtions using the soft assigns counter to average the incoming radiance per lobe (getting rid of the PDF dependency) TODO: + // maybe drop this code const embree::vfloat zeros(0.0f); const embree::vfloat ones(1.0f); - const int cnt = (vmm._numComponents+VMM::VectorSize-1) / VMM::VectorSize; - - if(numSamples == 0) + const int cnt = (vmm._numComponents + VMM::VectorSize - 1) / VMM::VectorSize; + + if (numSamples == 0) { return; } @@ -1437,9 +1408,9 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory::updateFluen embree::vfloat sumPdfs[VMM::NumVectors]; embree::vfloat pdfs(1.0f); embree::Vec3 > sumFluenceRGBWeights[VMM::NumVectors]; - float sumFluence {0.f}; - Vector3 sumFluenceRGB {0.f, 0.f, 0.f}; - Vector3 sumFluenceRGBMC {0.f, 0.f, 0.f}; + float sumFluence{0.f}; + Vector3 sumFluenceRGB{0.f, 0.f, 0.f}; + Vector3 sumFluenceRGBMC{0.f, 0.f, 0.f}; typename VMM::SoftAssignment softAssign; for (int k = 0; k < cnt; k++) @@ -1453,7 +1424,7 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory::updateFluen for (size_t n = 0; n < numSamples; n++) { const Vector3 sampleDirection(samples[n].direction.x, samples[n].direction.y, samples[n].direction.z); - embree::Vec3< embree::vfloat > sampleDirectionVec(sampleDirection[0], sampleDirection[1], sampleDirection[2]); + embree::Vec3 > sampleDirectionVec(sampleDirection[0], sampleDirection[1], sampleDirection[2]); Vector3 radianceIn(samples[n].radianceIn.x, samples[n].radianceIn.y, samples[n].radianceIn.z); sumFluence += samples[n].weight; @@ -1463,7 +1434,6 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory::updateFluen { for (size_t k = 0; k < cnt; k++) { - const embree::vfloat cosTheta = embree::dot(sampleDirectionVec, vmm._meanDirections[k]); const embree::vfloat cosThetaMinusOne = embree::min(cosTheta - ones, zeros); OPENPGL_ASSERT(embree::isvalid(pdfs)); @@ -1481,11 +1451,11 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory::updateFluen for (int k = 0; k < cnt; k++) { - sumFluenceRGBWeights[k].x = select( sumPdfs[k] > 0.0f, sumFluenceRGBWeights[k].x / sumPdfs[k], zeros) * (4.0f * M_PI_F); + sumFluenceRGBWeights[k].x = select(sumPdfs[k] > 0.0f, sumFluenceRGBWeights[k].x / sumPdfs[k], zeros) * (4.0f * M_PI_F); OPENPGL_ASSERT(embree::isvalid(sumFluenceRGBWeights[k].x)); - sumFluenceRGBWeights[k].y = select( sumPdfs[k] > 0.0f, sumFluenceRGBWeights[k].y / sumPdfs[k], zeros) * (4.0f * M_PI_F); + sumFluenceRGBWeights[k].y = select(sumPdfs[k] > 0.0f, sumFluenceRGBWeights[k].y / sumPdfs[k], zeros) * (4.0f * M_PI_F); OPENPGL_ASSERT(embree::isvalid(sumFluenceRGBWeights[k].y)); - sumFluenceRGBWeights[k].z = select( sumPdfs[k] > 0.0f, sumFluenceRGBWeights[k].z / sumPdfs[k], zeros) * (4.0f * M_PI_F); + sumFluenceRGBWeights[k].z = select(sumPdfs[k] > 0.0f, sumFluenceRGBWeights[k].z / sumPdfs[k], zeros) * (4.0f * M_PI_F); OPENPGL_ASSERT(embree::isvalid(sumFluenceRGBWeights[k].z)); sumFluenceRGB.x += embree::reduce_add(sumFluenceRGBWeights[k].x); sumFluenceRGB.y += embree::reduce_add(sumFluenceRGBWeights[k].y); @@ -1501,7 +1471,7 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory::updateFluen vmm._fluenceRGBWeightsWithMIS[k].x = (vmm._fluenceRGBWeightsWithMIS[k].x * (1.f - alpha)) + alpha * sumFluenceRGBWeights[k].x; vmm._fluenceRGBWeightsWithMIS[k].y = (vmm._fluenceRGBWeightsWithMIS[k].y * (1.f - alpha)) + alpha * sumFluenceRGBWeights[k].y; vmm._fluenceRGBWeightsWithMIS[k].z = (vmm._fluenceRGBWeightsWithMIS[k].z * (1.f - alpha)) + alpha * sumFluenceRGBWeights[k].z; - } + } vmm._fluenceRGB = (1.f - alpha) * vmm._fluenceRGB + alpha * sumFluenceRGB; vmm._fluence = (1.f - alpha) * vmm._fluence + alpha * sumFluence; @@ -1511,50 +1481,50 @@ void ParallaxAwareVonMisesFisherWeightedEMFactory::updateFluen } #endif -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Configuration::init() +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::Configuration::init() { - maxMeanCosine = KappaToMeanCosine(maxKappa); + maxMeanCosine = KappaToMeanCosine(maxKappa); } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Configuration::serialize(std::ostream& stream) const +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::Configuration::serialize(std::ostream &stream) const { - stream.write(reinterpret_cast(&initK), sizeof(size_t)); - stream.write(reinterpret_cast(&initKappa), sizeof(float)); - stream.write(reinterpret_cast(&maxK), sizeof(size_t)); - stream.write(reinterpret_cast(&maxEMIterrations), sizeof(size_t)); + stream.write(reinterpret_cast(&initK), sizeof(size_t)); + stream.write(reinterpret_cast(&initKappa), sizeof(float)); + stream.write(reinterpret_cast(&maxK), sizeof(size_t)); + stream.write(reinterpret_cast(&maxEMIterrations), sizeof(size_t)); - stream.write(reinterpret_cast(&maxKappa), sizeof(float)); - stream.write(reinterpret_cast(&maxMeanCosine), sizeof(float)); - stream.write(reinterpret_cast(&convergenceThreshold), sizeof(float)); + stream.write(reinterpret_cast(&maxKappa), sizeof(float)); + stream.write(reinterpret_cast(&maxMeanCosine), sizeof(float)); + stream.write(reinterpret_cast(&convergenceThreshold), sizeof(float)); - stream.write(reinterpret_cast(&weightPrior), sizeof(float)); + stream.write(reinterpret_cast(&weightPrior), sizeof(float)); - stream.write(reinterpret_cast(&meanCosinePriorStrength), sizeof(float)); - stream.write(reinterpret_cast(&meanCosinePrior), sizeof(float)); + stream.write(reinterpret_cast(&meanCosinePriorStrength), sizeof(float)); + stream.write(reinterpret_cast(&meanCosinePrior), sizeof(float)); } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Configuration::deserialize(std::istream& stream) +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::Configuration::deserialize(std::istream &stream) { - stream.read(reinterpret_cast(&initK), sizeof(size_t)); - stream.read(reinterpret_cast(&initKappa), sizeof(float)); - stream.read(reinterpret_cast(&maxK), sizeof(size_t)); - stream.read(reinterpret_cast(&maxEMIterrations), sizeof(size_t)); + stream.read(reinterpret_cast(&initK), sizeof(size_t)); + stream.read(reinterpret_cast(&initKappa), sizeof(float)); + stream.read(reinterpret_cast(&maxK), sizeof(size_t)); + stream.read(reinterpret_cast(&maxEMIterrations), sizeof(size_t)); - stream.read(reinterpret_cast(&maxKappa), sizeof(float)); - stream.read(reinterpret_cast(&maxMeanCosine), sizeof(float)); - stream.read(reinterpret_cast(&convergenceThreshold), sizeof(float)); + stream.read(reinterpret_cast(&maxKappa), sizeof(float)); + stream.read(reinterpret_cast(&maxMeanCosine), sizeof(float)); + stream.read(reinterpret_cast(&convergenceThreshold), sizeof(float)); - stream.read(reinterpret_cast(&weightPrior), sizeof(float)); + stream.read(reinterpret_cast(&weightPrior), sizeof(float)); - stream.read(reinterpret_cast(&meanCosinePriorStrength), sizeof(float)); - stream.read(reinterpret_cast(&meanCosinePrior), sizeof(float)); + stream.read(reinterpret_cast(&meanCosinePriorStrength), sizeof(float)); + stream.read(reinterpret_cast(&meanCosinePrior), sizeof(float)); } -template -std::string ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Configuration::toString() const +template +std::string ParallaxAwareVonMisesFisherWeightedEMFactory::Configuration::toString() const { std::stringstream ss; ss << "Configuration:" << std::endl; @@ -1572,59 +1542,58 @@ std::string ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::Con return ss.str(); } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::PartialFittingMask::resetToFalse() +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::PartialFittingMask::resetToFalse() { const embree::vbool vFalse(false); - for (size_t k = 0; k < ( (VMM::MaxComponents + (VMM::VectorSize -1)) / VMM::VectorSize); k++) + for (size_t k = 0; k < ((VMM::MaxComponents + (VMM::VectorSize - 1)) / VMM::VectorSize); k++) { mask[k] = vFalse; } } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::PartialFittingMask::resetToTrue(const size_t &numComponents) +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::PartialFittingMask::resetToTrue(const size_t &numComponents) { const embree::vbool vTrue(true); - const int cnt = (numComponents+VMM::VectorSize-1) / VMM::VectorSize; + const int cnt = (numComponents + VMM::VectorSize - 1) / VMM::VectorSize; for (size_t k = 0; k < cnt; k++) { mask[k] = vTrue; } - const div_t tmp = div( numComponents, VMM::VectorSize); + const div_t tmp = div(numComponents, VMM::VectorSize); for (size_t k = tmp.rem; k < VMM::VectorSize; k++) { clear(mask[tmp.quot], k); } } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::PartialFittingMask::setToTrue(const size_t &idx) +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::PartialFittingMask::setToTrue(const size_t &idx) { - const div_t tmp = div( idx, VMM::VectorSize); + const div_t tmp = div(idx, VMM::VectorSize); set(mask[tmp.quot], tmp.rem); } -template -void ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::PartialFittingMask::setToFalse(const size_t &idx) +template +void ParallaxAwareVonMisesFisherWeightedEMFactory::PartialFittingMask::setToFalse(const size_t &idx) { - const div_t tmp = div( idx, VMM::VectorSize); + const div_t tmp = div(idx, VMM::VectorSize); clear(mask[tmp.quot], tmp.rem); } - -template -std::string ParallaxAwareVonMisesFisherWeightedEMFactory< TVMMDistribution>::PartialFittingMask::toString() const +template +std::string ParallaxAwareVonMisesFisherWeightedEMFactory::PartialFittingMask::toString() const { std::stringstream ss; - ss << "PartialFittingMask:" << std::endl; - for (size_t k = 0; k < VMM::MaxComponents; k++) - { - const div_t tmp = div( k, VMM::VectorSize); - ss << "mask[" << k << "]: " << mask[tmp.quot][tmp.rem] << std::endl; - } + ss << "PartialFittingMask:" << std::endl; + for (size_t k = 0; k < VMM::MaxComponents; k++) + { + const div_t tmp = div(k, VMM::VectorSize); + ss << "mask[" << k << "]: " << mask[tmp.quot][tmp.rem] << std::endl; + } return ss.str(); } -} +} // namespace openpgl diff --git a/openpgl/directional/vmm/VMMChiSquareComponentMerger.h b/openpgl/directional/vmm/VMMChiSquareComponentMerger.h index 0c22984..d27e678 100644 --- a/openpgl/directional/vmm/VMMChiSquareComponentMerger.h +++ b/openpgl/directional/vmm/VMMChiSquareComponentMerger.h @@ -4,58 +4,57 @@ #pragma once #include "../../openpgl_common.h" -#include "VMMChiSquareComponentSplitter.h" #include "ParallaxAwareVonMisesFisherMixture.h" +#include "VMMChiSquareComponentSplitter.h" namespace openpgl { -template +template struct VonMisesFisherChiSquareComponentMerger { -public: + public: typedef typename TVMMFactory::Distribution VMM; typedef typename TVMMFactory::SufficientStatistics SufficientStatistics; typedef typename VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics ComponentSplitStatistics; - //typedef std::integral_constant NumVectors; + // typedef std::integral_constant NumVectors; - float MergeNext (VMM &vmm) const; + float MergeNext(VMM &vmm) const; - bool ThresholdedMergeNext (VMM &vmm, const float &mergeThreshold, float &mergeCost) const; + bool ThresholdedMergeNext(VMM &vmm, const float &mergeThreshold, float &mergeCost) const; - bool ThresholdedMergeNext (VMM &vmm, const float &mergeThreshold, float &mergeCost, SufficientStatistics &suffStats, ComponentSplitStatistics &splitStats) const; + bool ThresholdedMergeNext(VMM &vmm, const float &mergeThreshold, float &mergeCost, SufficientStatistics &suffStats, ComponentSplitStatistics &splitStats) const; - float CalculateMergeCost (const VMM &vmm, const size_t &idx0, const size_t &idx1) const; + float CalculateMergeCost(const VMM &vmm, const size_t &idx0, const size_t &idx1) const; size_t PerformMerging(VMM &vmm, const float &mergeThreshold) const; size_t PerformMerging(VMM &vmm, const float &mergeThreshold, SufficientStatistics &suffStats, ComponentSplitStatistics &splitStats) const; -private: - inline float _IntegratedProduct(const Vector3 &meanDirection0, const float &kappa0, const float &normalization0, const Vector3 &meanDirection1, const float &kappa1, const float &normalization1) const; - - inline float _IntegratedDivision(const Vector3 &meanDirection0, const float &kappa0, const float &normalization0, const Vector3 &meanDirection1, const float &kappa1, const float &normalization1, const float &eMinus2Kappa1) const; + private: + inline float _IntegratedProduct(const Vector3 &meanDirection0, const float &kappa0, const float &normalization0, const Vector3 &meanDirection1, const float &kappa1, + const float &normalization1) const; - inline float _Product( const Vector3 &meanDirection0, const float &kappa0, const float &normalization0, - const Vector3 &meanDirection1, const float &kappa1, const float &normalization1, - Vector3 &meanDirection, float &kappa, float &normalization ) const; + inline float _IntegratedDivision(const Vector3 &meanDirection0, const float &kappa0, const float &normalization0, const Vector3 &meanDirection1, const float &kappa1, + const float &normalization1, const float &eMinus2Kappa1) const; + inline float _Product(const Vector3 &meanDirection0, const float &kappa0, const float &normalization0, const Vector3 &meanDirection1, const float &kappa1, + const float &normalization1, Vector3 &meanDirection, float &kappa, float &normalization) const; }; -template +template size_t VonMisesFisherChiSquareComponentMerger::PerformMerging(VMM &vmm, const float &mergeThreshold) const { - bool stopMerging = false; size_t totalMergeCount = 0; - //while (vmm._numComponents > 1 && !stopMerging) + // while (vmm._numComponents > 1 && !stopMerging) while (vmm._numComponents > VMM::VectorSize && !stopMerging) { float mergeCost = 0.0f; stopMerging = true; - bool mergedComponents = ThresholdedMergeNext(vmm, mergeThreshold,mergeCost); + bool mergedComponents = ThresholdedMergeNext(vmm, mergeThreshold, mergeCost); stopMerging = !mergedComponents; - //std::cout << "merge: " << "\tmergedComponents: " << mergedComponents << "\tmergeCost: " << mergeCost << std::endl; + // std::cout << "merge: " << "\tmergedComponents: " << mergedComponents << "\tmergeCost: " << mergeCost << std::endl; if (mergedComponents) { totalMergeCount++; @@ -64,54 +63,50 @@ size_t VonMisesFisherChiSquareComponentMerger::PerformMerging(VMM & return totalMergeCount; } -template -size_t VonMisesFisherChiSquareComponentMerger::PerformMerging(VMM &vmm, const float &mergeThreshold, SufficientStatistics &suffStats, ComponentSplitStatistics &splitStats) const +template +size_t VonMisesFisherChiSquareComponentMerger::PerformMerging(VMM &vmm, const float &mergeThreshold, SufficientStatistics &suffStats, + ComponentSplitStatistics &splitStats) const { bool stopMerging = false; size_t totalMergeCount = 0; - //while (vmm._numComponents > 1 && !stopMerging) + // while (vmm._numComponents > 1 && !stopMerging) while (vmm._numComponents > VMM::VectorSize && !stopMerging) { float mergeCost = 0.0f; stopMerging = true; - bool mergedComponents = ThresholdedMergeNext(vmm, mergeThreshold,mergeCost, suffStats, splitStats); + bool mergedComponents = ThresholdedMergeNext(vmm, mergeThreshold, mergeCost, suffStats, splitStats); stopMerging = !mergedComponents; - //std::cout << "merge: " << "\tmergedComponents: " << mergedComponents << "\tmergeCost: " << mergeCost << std::endl; + // std::cout << "merge: " << "\tmergedComponents: " << mergedComponents << "\tmergeCost: " << mergeCost << std::endl; if (mergedComponents) { totalMergeCount++; } } #ifdef OPENPGL_SHOW_PRINT_OUTS - std::cout << "PerformMerging: totalMergeCount = " << totalMergeCount << "\t mergeThreshold: " << mergeThreshold<< std::endl; + std::cout << "PerformMerging: totalMergeCount = " << totalMergeCount << "\t mergeThreshold: " << mergeThreshold << std::endl; #endif return totalMergeCount; } - -template -float VonMisesFisherChiSquareComponentMerger::CalculateMergeCost (const VMM &vmm, const size_t &idx0, const size_t &idx1) const +template +float VonMisesFisherChiSquareComponentMerger::CalculateMergeCost(const VMM &vmm, const size_t &idx0, const size_t &idx1) const { - const div_t div0 = div( idx0, VMM::VectorSize); + const div_t div0 = div(idx0, VMM::VectorSize); float weight0 = vmm._weights[div0.quot][div0.rem]; const float kappa0 = vmm._kappas[div0.quot][div0.rem]; - const Vector3 meanDirection0 = Vector3( vmm._meanDirections[div0.quot].x[div0.rem], - vmm._meanDirections[div0.quot].y[div0.rem], - vmm._meanDirections[div0.quot].z[div0.rem]); + const Vector3 meanDirection0 = Vector3(vmm._meanDirections[div0.quot].x[div0.rem], vmm._meanDirections[div0.quot].y[div0.rem], vmm._meanDirections[div0.quot].z[div0.rem]); const float meanCosine0 = vmm._meanCosines[div0.quot][div0.rem]; const float normalization0 = vmm._normalizations[div0.quot][div0.rem]; - const div_t div1 = div( idx1, VMM::VectorSize); + const div_t div1 = div(idx1, VMM::VectorSize); float weight1 = vmm._weights[div1.quot][div1.rem]; const float kappa1 = vmm._kappas[div1.quot][div1.rem]; - const Vector3 meanDirection1 = Vector3( vmm._meanDirections[div1.quot].x[div1.rem], - vmm._meanDirections[div1.quot].y[div1.rem], - vmm._meanDirections[div1.quot].z[div1.rem]); + const Vector3 meanDirection1 = Vector3(vmm._meanDirections[div1.quot].x[div1.rem], vmm._meanDirections[div1.quot].y[div1.rem], vmm._meanDirections[div1.quot].z[div1.rem]); const float meanCosine1 = vmm._meanCosines[div1.quot][div1.rem]; const float normalization1 = vmm._normalizations[div1.quot][div1.rem]; - if ( idx0 == idx1 ) + if (idx0 == idx1) { weight0 /= 2.0f; weight1 /= 2.0f; @@ -127,14 +122,14 @@ float VonMisesFisherChiSquareComponentMerger::CalculateMergeCost (c Vector3 meanDirection = weight0 * meanCosine0 * meanDirection0 + weight1 * meanCosine1 * meanDirection1; meanDirection /= weight; meanCosine = meanDirection.x * meanDirection.x + meanDirection.y * meanDirection.y + meanDirection.z * meanDirection.z; - if ( meanCosine > 0.f) + if (meanCosine > 0.f) { - meanCosine = std::sqrt( meanCosine ); + meanCosine = std::sqrt(meanCosine); kappa = MeanCosineToKappa(meanCosine); kappa = kappa < 1e-3f ? 0.f : kappa; - //eMin2Kappa = math::fastexp( -2.0f * kappa ); - eMinus2Kappa = embree::exp( -2.0f * kappa ); - normalization = kappa / ( 2.0f * M_PI_F * ( 1.0f - eMinus2Kappa ) ); + // eMin2Kappa = math::fastexp( -2.0f * kappa ); + eMinus2Kappa = embree::exp(-2.0f * kappa); + normalization = kappa / (2.0f * M_PI_F * (1.0f - eMinus2Kappa)); meanDirection /= meanCosine; } @@ -147,51 +142,44 @@ float VonMisesFisherChiSquareComponentMerger::CalculateMergeCost (c float kappa00; float normalization00; Vector3 meanDirection00; - float scale00 = _Product( meanDirection0, kappa0, normalization0, - meanDirection0, kappa0, normalization0, - meanDirection00, kappa00, normalization00); + float scale00 = _Product(meanDirection0, kappa0, normalization0, meanDirection0, kappa0, normalization0, meanDirection00, kappa00, normalization00); float weight11 = weight1 * weight1; float kappa11; float normalization11; Vector3 meanDirection11; - float scale11 = _Product( meanDirection1, kappa1, normalization1, - meanDirection1, kappa1, normalization1, - meanDirection11, kappa11, normalization11); + float scale11 = _Product(meanDirection1, kappa1, normalization1, meanDirection1, kappa1, normalization1, meanDirection11, kappa11, normalization11); float weight01 = weight0 * weight1; float kappa01; float normalization01; Vector3 meanDirection01; - float scale01 = _Product( meanDirection0, kappa0, normalization0, - meanDirection1, kappa1, normalization1, - meanDirection01, kappa01, normalization01); + float scale01 = _Product(meanDirection0, kappa0, normalization0, meanDirection1, kappa1, normalization1, meanDirection01, kappa01, normalization01); float chiSquareIJ = 0.0f; - chiSquareIJ += (weight00 / weight) * (scale00 * _IntegratedDivision( meanDirection00, kappa00, normalization00, -meanDirection, kappa, normalization, eMinus2Kappa)); - chiSquareIJ += (weight11 / weight) * ( scale11 * _IntegratedDivision( meanDirection11, kappa11, normalization11, -meanDirection, kappa, normalization, eMinus2Kappa)); - chiSquareIJ += 2.0f * ( weight01 / weight) * ( scale01 * _IntegratedDivision( meanDirection01, kappa01, normalization01, -meanDirection, kappa, normalization, eMinus2Kappa)); + chiSquareIJ += (weight00 / weight) * (scale00 * _IntegratedDivision(meanDirection00, kappa00, normalization00, -meanDirection, kappa, normalization, eMinus2Kappa)); + chiSquareIJ += (weight11 / weight) * (scale11 * _IntegratedDivision(meanDirection11, kappa11, normalization11, -meanDirection, kappa, normalization, eMinus2Kappa)); + chiSquareIJ += 2.0f * (weight01 / weight) * (scale01 * _IntegratedDivision(meanDirection01, kappa01, normalization01, -meanDirection, kappa, normalization, eMinus2Kappa)); chiSquareIJ -= weight; return chiSquareIJ; - } -template -bool VonMisesFisherChiSquareComponentMerger::ThresholdedMergeNext (VMM &vmm, const float &mergeThreshold, float &mergeCost) const +template +bool VonMisesFisherChiSquareComponentMerger::ThresholdedMergeNext(VMM &vmm, const float &mergeThreshold, float &mergeCost) const { - //std::cout << vmm.toString()<::max(); bool foundMergeCandidates = false; - for (size_t i = 0; i < K-1; i++) + for (size_t i = 0; i < K - 1; i++) { - for (size_t j = i+1; j < K; j++ ) + for (size_t j = i + 1; j < K; j++) { - float mergeCost = CalculateMergeCost(vmm, i,j); + float mergeCost = CalculateMergeCost(vmm, i, j); if (mergeCost < mergeThreshold && mergeCost < minMergeCost) { mergeCandidateI = i; @@ -207,16 +195,15 @@ bool VonMisesFisherChiSquareComponentMerger::ThresholdedMergeNext ( vmm.mergeComponents(mergeCandidateI, mergeCandidateJ); mergeCost = minMergeCost; #ifdef OPENPGL_SHOW_PRINT_OUTS - std::cout << "merge: " << "\tidx0: " << mergeCandidateI << "\tidx1: " << mergeCandidateJ << "\tK: " << vmm._numComponents < -bool VonMisesFisherChiSquareComponentMerger::ThresholdedMergeNext (VMM &vmm, const float &mergeThreshold, float &mergeCost, SufficientStatistics &suffStats, ComponentSplitStatistics &splitStats) const +template +bool VonMisesFisherChiSquareComponentMerger::ThresholdedMergeNext(VMM &vmm, const float &mergeThreshold, float &mergeCost, SufficientStatistics &suffStats, + ComponentSplitStatistics &splitStats) const { OPENPGL_ASSERT(splitStats.isValid()); int K = vmm._numComponents; @@ -225,16 +212,14 @@ bool VonMisesFisherChiSquareComponentMerger::ThresholdedMergeNext ( float minMergeCost = std::numeric_limits::max(); bool foundMergeCandidates = false; - for (size_t i = 0; i < K-1; i++) + for (size_t i = 0; i < K - 1; i++) { const div_t tmpI = div(i, static_cast(VMM::VectorSize)); - for (size_t j = i+1; j < K; j++ ) + for (size_t j = i + 1; j < K; j++) { const div_t tmpJ = div(j, static_cast(VMM::VectorSize)); - float mergeCost = CalculateMergeCost(vmm, i,j); - if (mergeCost < mergeThreshold && mergeCost < minMergeCost - && splitStats.numSamples[tmpI.quot][tmpI.rem] > 0.0f - && splitStats.numSamples[tmpJ.quot][tmpJ.rem] > 0.0f) + float mergeCost = CalculateMergeCost(vmm, i, j); + if (mergeCost < mergeThreshold && mergeCost < minMergeCost && splitStats.numSamples[tmpI.quot][tmpI.rem] > 0.0f && splitStats.numSamples[tmpJ.quot][tmpJ.rem] > 0.0f) { mergeCandidateI = i; mergeCandidateJ = j; @@ -247,9 +232,9 @@ bool VonMisesFisherChiSquareComponentMerger::ThresholdedMergeNext ( if (foundMergeCandidates) { #ifdef OPENPGL_SHOW_PRINT_OUTS - std::cout << "merge: " << "\tidx0: " << mergeCandidateI << "\tidx1: " << mergeCandidateJ << "\tK: " << vmm._numComponents <::ThresholdedMergeNext ( OPENPGL_ASSERT(suffStats.isValid()); mergeCost = minMergeCost; - //OPENPGL_ASSERT(vmm._numComponents == suffStats.numComponents); + // OPENPGL_ASSERT(vmm._numComponents == suffStats.numComponents); OPENPGL_ASSERT(vmm._numComponents == splitStats.numComponents); - } return foundMergeCandidates; - } -template -float VonMisesFisherChiSquareComponentMerger::MergeNext (VMM &vmm) const +template +float VonMisesFisherChiSquareComponentMerger::MergeNext(VMM &vmm) const { int K = vmm._numComponents; int mergeCandidateI = 0; int mergeCandidateJ = 0; float minMergeCost = std::numeric_limits::max(); - for (size_t i = 0; i < K-1; i++) + for (size_t i = 0; i < K - 1; i++) { - for (size_t j = i+1; j < K; j++ ) + for (size_t j = i + 1; j < K; j++) { - float mergeCost = CalculateMergeCost(vmm, i,j); + float mergeCost = CalculateMergeCost(vmm, i, j); if (mergeCost < minMergeCost) { mergeCandidateI = i; @@ -303,22 +286,22 @@ float VonMisesFisherChiSquareComponentMerger::MergeNext (VMM &vmm) vmm.mergeComponents(mergeCandidateI, mergeCandidateJ); return minMergeCost; - } -template -float VonMisesFisherChiSquareComponentMerger::_IntegratedProduct(const Vector3 &meanDirection0, const float &kappa0, const float &normalization0, const Vector3 &meanDirection1, const float &kappa1, const float &normalization1) const +template +float VonMisesFisherChiSquareComponentMerger::_IntegratedProduct(const Vector3 &meanDirection0, const float &kappa0, const float &normalization0, + const Vector3 &meanDirection1, const float &kappa1, const float &normalization1) const { Vector3 productMeanDirection = kappa0 * meanDirection0 + kappa1 * meanDirection1; - float productKappa = embree::sqrt( dot( productMeanDirection, productMeanDirection)); + float productKappa = embree::sqrt(dot(productMeanDirection, productMeanDirection)); float productNormalization = 1.0f / (4.0f * M_PI_F); float productEMinus2Kappa = 1.0f; - if ( productKappa > 1e-3f) + if (productKappa > 1e-3f) { productEMinus2Kappa = std::exp(-2.0f * productKappa); - productNormalization = productKappa / (2.0f * M_PI_F * ( 1.0f - productEMinus2Kappa )); + productNormalization = productKappa / (2.0f * M_PI_F * (1.0f - productEMinus2Kappa)); productMeanDirection /= productKappa; } else @@ -327,27 +310,29 @@ float VonMisesFisherChiSquareComponentMerger::_IntegratedProduct(co productMeanDirection = meanDirection0; } - float scale = ( normalization0 * normalization1 ) / productNormalization; - float cosTheta0 = dot( meanDirection0, productMeanDirection); - float cosTheta1 = dot( meanDirection1, productMeanDirection); - scale *= std::exp( kappa0 * ( cosTheta0 - 1.0f ) + kappa1 * ( cosTheta1 - 1.0f ) ); + float scale = (normalization0 * normalization1) / productNormalization; + float cosTheta0 = dot(meanDirection0, productMeanDirection); + float cosTheta1 = dot(meanDirection1, productMeanDirection); + scale *= std::exp(kappa0 * (cosTheta0 - 1.0f) + kappa1 * (cosTheta1 - 1.0f)); return scale; } -template -float VonMisesFisherChiSquareComponentMerger::_IntegratedDivision(const Vector3 &meanDirection0, const float &kappa0, const float &normalization0, const Vector3 &meanDirection1, const float &kappa1, const float &normalization1, const float &eMinus2Kappa1) const +template +float VonMisesFisherChiSquareComponentMerger::_IntegratedDivision(const Vector3 &meanDirection0, const float &kappa0, const float &normalization0, + const Vector3 &meanDirection1, const float &kappa1, const float &normalization1, + const float &eMinus2Kappa1) const { Vector3 productMeanDirection = kappa0 * meanDirection0 + kappa1 * meanDirection1; - float productKappa = embree::sqrt( dot( productMeanDirection, productMeanDirection)); + float productKappa = embree::sqrt(dot(productMeanDirection, productMeanDirection)); float productNormalization = 1.0f / (4.0f * M_PI_F); float productEMinus2Kappa = 1.0f; - if ( productKappa > 1e-3f) + if (productKappa > 1e-3f) { productEMinus2Kappa = std::exp(-2.0f * productKappa); - productNormalization = productKappa / (2.0f * M_PI_F * ( 1.0f - productEMinus2Kappa )); + productNormalization = productKappa / (2.0f * M_PI_F * (1.0f - productEMinus2Kappa)); productMeanDirection /= productKappa; } else @@ -356,29 +341,29 @@ float VonMisesFisherChiSquareComponentMerger::_IntegratedDivision(c productMeanDirection = meanDirection0; } - float scale = ( normalization0 * normalization1 ) / productNormalization; - float cosTheta0 = dot( meanDirection0, productMeanDirection); - float cosTheta1 = dot( meanDirection1, productMeanDirection); - scale *= (4.0f * M_PI_F * M_PI_F * ( 1.0f - eMinus2Kappa1) ) / (kappa1 * kappa1); - scale *= std::exp( (kappa0 * ( cosTheta0 - 1.0f ) + kappa1 * ( cosTheta1 - 1.0f )) + (2.0f * kappa1) ); + float scale = (normalization0 * normalization1) / productNormalization; + float cosTheta0 = dot(meanDirection0, productMeanDirection); + float cosTheta1 = dot(meanDirection1, productMeanDirection); + scale *= (4.0f * M_PI_F * M_PI_F * (1.0f - eMinus2Kappa1)) / (kappa1 * kappa1); + scale *= std::exp((kappa0 * (cosTheta0 - 1.0f) + kappa1 * (cosTheta1 - 1.0f)) + (2.0f * kappa1)); return scale; } -template -float VonMisesFisherChiSquareComponentMerger::_Product(const Vector3 &meanDirection0, const float &kappa0, const float &normalization0, - const Vector3 &meanDirection1, const float &kappa1, const float &normalization1, - Vector3 &productMeanDirection, float &productKappa, float &productNormalization) const +template +float VonMisesFisherChiSquareComponentMerger::_Product(const Vector3 &meanDirection0, const float &kappa0, const float &normalization0, const Vector3 &meanDirection1, + const float &kappa1, const float &normalization1, Vector3 &productMeanDirection, float &productKappa, + float &productNormalization) const { productMeanDirection = kappa0 * meanDirection0 + kappa1 * meanDirection1; - productKappa = embree::sqrt( dot( productMeanDirection, productMeanDirection)); + productKappa = embree::sqrt(dot(productMeanDirection, productMeanDirection)); productNormalization = 1.0f / (4.0f * M_PI_F); float productEMinus2Kappa = 1.0f; - if ( productKappa > 1e-3f) + if (productKappa > 1e-3f) { productEMinus2Kappa = std::exp(-2.0f * productKappa); - productNormalization = productKappa / (2.0f * M_PI_F * ( 1.0f - productEMinus2Kappa )); + productNormalization = productKappa / (2.0f * M_PI_F * (1.0f - productEMinus2Kappa)); productMeanDirection /= productKappa; } else @@ -387,13 +372,13 @@ float VonMisesFisherChiSquareComponentMerger::_Product(const Vector productMeanDirection = meanDirection0; } - float scale = ( normalization0 * normalization1 ) / productNormalization; - float cosTheta0 = dot( meanDirection0, productMeanDirection); - float cosTheta1 = dot( meanDirection1, productMeanDirection); + float scale = (normalization0 * normalization1) / productNormalization; + float cosTheta0 = dot(meanDirection0, productMeanDirection); + float cosTheta1 = dot(meanDirection1, productMeanDirection); - scale *= std::exp( kappa0 * ( cosTheta0 - 1.0f ) + kappa1 * ( cosTheta1 - 1.0f ) ); + scale *= std::exp(kappa0 * (cosTheta0 - 1.0f) + kappa1 * (cosTheta1 - 1.0f)); return scale; } -} +} // namespace openpgl diff --git a/openpgl/directional/vmm/VMMChiSquareComponentSplitter.h b/openpgl/directional/vmm/VMMChiSquareComponentSplitter.h index 336f6f6..456a77a 100644 --- a/openpgl/directional/vmm/VMMChiSquareComponentSplitter.h +++ b/openpgl/directional/vmm/VMMChiSquareComponentSplitter.h @@ -3,168 +3,165 @@ #pragma once -#include "../../openpgl_common.h" -#include "../../data/SampleData.h" -#include "ParallaxAwareVonMisesFisherMixture.h" - #include #include #include -#include - #include #include +#include + +#include "../../data/SampleData.h" +#include "../../openpgl_common.h" +#include "ParallaxAwareVonMisesFisherMixture.h" #define OPENPGL_USE_LOGMAP #define OPENPGL_ZERO_MEAN -//#define OPENPGL_USE_THREE_SPLIT +// #define OPENPGL_USE_THREE_SPLIT namespace openpgl { struct ComponentSplitinfo { - Vector2 mean {0.0f}; + Vector2 mean{0.0f}; Vector3 covariance{0.0f}; - float eigenValue0 {0.0f}; - float eigenValue1 {0.0f}; + float eigenValue0{0.0f}; + float eigenValue1{0.0f}; - Vector2 eigenVector0 {0.0f}; - Vector2 eigenVector1 {0.0f}; + Vector2 eigenVector0{0.0f}; + Vector2 eigenVector1{0.0f}; std::string toString() const; }; -template +template struct VonMisesFisherChiSquareComponentSplitter { - -public: + public: typedef typename TVMMFactory::Distribution VMM; typedef TVMMFactory VMMFactory; typedef typename VMMFactory::SufficientStatistics SufficientStatistics; typedef typename VMMFactory::PartialFittingMask PartialFittingMask; -struct SplitCandidate -{ - size_t componentIndex; - float chiSquareEst; - - bool operator<( const SplitCandidate &sc ) const + struct SplitCandidate { - return chiSquareEst < sc.chiSquareEst; - } - - bool operator>( const SplitCandidate &sc ) const - { - return chiSquareEst > sc.chiSquareEst; - } -}; - -struct ComponentSplitStatistics -{ + size_t componentIndex; + float chiSquareEst; - ComponentSplitStatistics() = default; - - embree::vfloat chiSquareMCEstimates[VMM::NumVectors]; - embree::Vec2 > splitMeans[VMM::NumVectors]; - embree::Vec3 > splitWeightedSampleCovariances[VMM::NumVectors]; + bool operator<(const SplitCandidate &sc) const + { + return chiSquareEst < sc.chiSquareEst; + } - embree::vfloat numSamples[VMM::NumVectors]; - embree::vfloat sumWeights[VMM::NumVectors]; + bool operator>(const SplitCandidate &sc) const + { + return chiSquareEst > sc.chiSquareEst; + } + }; - embree::vfloat sumAssignedSamples[VMM::NumVectors]; + struct ComponentSplitStatistics + { + ComponentSplitStatistics() = default; - size_t numComponents{0}; + embree::vfloat chiSquareMCEstimates[VMM::NumVectors]; + embree::Vec2 > splitMeans[VMM::NumVectors]; + embree::Vec3 > splitWeightedSampleCovariances[VMM::NumVectors]; - void clear(const size_t &_numComponents); - void clearAll(); + embree::vfloat numSamples[VMM::NumVectors]; + embree::vfloat sumWeights[VMM::NumVectors]; - float getChiSquareEst(const size_t &idx) const; - float getSumChiSquareEst() const; - size_t getHighestChiSquareIdx() const; + embree::vfloat sumAssignedSamples[VMM::NumVectors]; - void mergeComponentStats(const size_t &idxI, const size_t &idxJ, const float &weightI, const Vector3 &meanDirectionI, const float &weightJ, const Vector3 &meanDirectionJ, const float &weightK, const Vector3 &meanDirectionK); + size_t numComponents{0}; - Vector2 getSplitMean(const size_t &idx) const; + void clear(const size_t &_numComponents); + void clearAll(); - Vector3 getSplitCovariance(const size_t &idx) const; + float getChiSquareEst(const size_t &idx) const; + float getSumChiSquareEst() const; + size_t getHighestChiSquareIdx() const; - std::vector getSplitCandidates() const; + void mergeComponentStats(const size_t &idxI, const size_t &idxJ, const float &weightI, const Vector3 &meanDirectionI, const float &weightJ, const Vector3 &meanDirectionJ, + const float &weightK, const Vector3 &meanDirectionK); - void decay( const float &alpha ); + Vector2 getSplitMean(const size_t &idx) const; - bool isValid() const; + Vector3 getSplitCovariance(const size_t &idx) const; - void serialize(std::ostream& stream) const; + std::vector getSplitCandidates() const; - void deserialize(std::istream& stream); + void decay(const float &alpha); - inline size_t getNumComponents() const - { - return numComponents; - } + bool isValid() const; - void setNumComponents(const size_t &n) - { - numComponents = n; - } + void serialize(std::ostream &stream) const; - std::string toString() const; + void deserialize(std::istream &stream); - bool operator==(const ComponentSplitStatistics& b) const; -}; + inline size_t getNumComponents() const + { + return numComponents; + } + void setNumComponents(const size_t &n) + { + numComponents = n; + } -void PerformSplitting(VMM &vmm, const float &splitThreshold, const float &mcEstimate, const SampleData *data, const size_t &numData, const typename VMMFactory::Configuration factoryCfg, const bool &doPartialRefit, const int &maxSplittingItr = -1) const; + std::string toString() const; -void PerformRecursiveSplitting(VMM &vmm, typename VMMFactory::SufficientStatistics &suffStats, const float &splitThreshold, const float &mcEstimate, const SampleData *data, const size_t &numData, const typename VMMFactory::Configuration factoryCfg) const; + bool operator==(const ComponentSplitStatistics &b) const; + }; -void PerformSplittingIteration(VMM &vmm, const float &splitThreshold) const; + void PerformSplitting(VMM &vmm, const float &splitThreshold, const float &mcEstimate, const SampleData *data, const size_t &numData, + const typename VMMFactory::Configuration factoryCfg, const bool &doPartialRefit, const int &maxSplittingItr = -1) const; -void CalculateSplitStatistics(const VMM &vmm, ComponentSplitStatistics &splitStats, const float &mcEstimate, const SampleData *data, const size_t &numData) const; + void PerformRecursiveSplitting(VMM &vmm, typename VMMFactory::SufficientStatistics &suffStats, const float &splitThreshold, const float &mcEstimate, const SampleData *data, + const size_t &numData, const typename VMMFactory::Configuration factoryCfg) const; -void UpdateSplitStatistics(const VMM &vmm, ComponentSplitStatistics &splitStats, const float &mcEstimate, const SampleData *data, const size_t &numData) const; + void PerformSplittingIteration(VMM &vmm, const float &splitThreshold) const; -bool SplitComponent(VMM &vmm, ComponentSplitStatistics &splitStats, SufficientStatistics &suffStats, const size_t idx) const; + void CalculateSplitStatistics(const VMM &vmm, ComponentSplitStatistics &splitStats, const float &mcEstimate, const SampleData *data, const size_t &numData) const; -bool SplitComponentIntoThree(VMM &vmm, ComponentSplitStatistics &splitStats, SufficientStatistics &suffStats, const size_t idx) const; + void UpdateSplitStatistics(const VMM &vmm, ComponentSplitStatistics &splitStats, const float &mcEstimate, const SampleData *data, const size_t &numData) const; -ComponentSplitinfo GetProjectedLocalDirections(const VMM &vmm, const size_t &idx, const SampleData *data, const size_t &numData, Vector3 *local2D) const; + bool SplitComponent(VMM &vmm, ComponentSplitStatistics &splitStats, SufficientStatistics &suffStats, const size_t idx) const; + bool SplitComponentIntoThree(VMM &vmm, ComponentSplitStatistics &splitStats, SufficientStatistics &suffStats, const size_t idx) const; + ComponentSplitinfo GetProjectedLocalDirections(const VMM &vmm, const size_t &idx, const SampleData *data, const size_t &numData, Vector3 *local2D) const; }; #ifndef OPENPGL_USE_LOGMAP -template +template inline Vec2Type Map3DTo2D(const Vec3Type &vec3D) { return Vec2Type(vec3D.x, vec3D.y); } -template +template inline Vec3Type Map2DTo3D(const Vec2Type &vec2D) { Vec3Type vec3D = Vec3Type(0.0f); vec3D.x = vec2D.x; vec3D.y = vec2D.y; - vec3D.z = embree::sqrt(1.0f - vec2D.x*vec2D.x - vec2D.y*vec2D.y); + vec3D.z = embree::sqrt(1.0f - vec2D.x * vec2D.x - vec2D.y * vec2D.y); return vec3D; } #else -//logMapping https://ronnybergmann.net/mvirt/manifolds/Sn/log.html -template +// logMapping https://ronnybergmann.net/mvirt/manifolds/Sn/log.html +template inline Vec2Type Map3DTo2D(const Vec3Type &vec3D) { Vec2Type vec2D(0.0f); - //OPENPGL_ASSERT((vec3D.z <= 1.0f && vec3D.z >= -1.0f)); + // OPENPGL_ASSERT((vec3D.z <= 1.0f && vec3D.z >= -1.0f)); ScalarType alpha = embree::fastapprox::acos(vec3D.z); ScalarType inv_sinc = alpha / embree::fastapprox::sin(alpha); // TODO: Needs to be implmented @@ -174,12 +171,12 @@ inline Vec2Type Map3DTo2D(const Vec3Type &vec3D) return vec2D; } -//expMapping https://ronnybergmann.net/mvirt/manifolds/Sn/exp.html -template +// expMapping https://ronnybergmann.net/mvirt/manifolds/Sn/exp.html +template inline Vec3Type Map2DTo3D(const Vec2Type &vec2D) { Vec3Type vec3D = Vec3Type(0.0f); - ScalarType length = embree::sqrt(vec2D.x*vec2D.x + vec2D.y*vec2D.y); + ScalarType length = embree::sqrt(vec2D.x * vec2D.x + vec2D.y * vec2D.y); OPENPGL_ASSERT(length < M_PI_F); ScalarType sinc = embree::fastapprox::sin(length) / length; @@ -190,32 +187,33 @@ inline Vec3Type Map2DTo3D(const Vec2Type &vec2D) return vec3D; } - #endif inline std::string ComponentSplitinfo::toString() const { std::stringstream ss; ss << "ComponentSplitinfo:" << std::endl; - //ss << "mean: " << mean << std::endl; - //ss << "covariance: " << covariance << std::endl; + // ss << "mean: " << mean << std::endl; + // ss << "covariance: " << covariance << std::endl; ss << "eigenValue0: " << eigenValue0 << std::endl; ss << "eigenValue1: " << eigenValue1 << std::endl; - //ss << "eigenVector0: " << eigenVector0 << std::endl; - //ss << "eigenVector1: " << eigenVector1 << std::endl; + // ss << "eigenVector0: " << eigenVector0 << std::endl; + // ss << "eigenVector1: " << eigenVector1 << std::endl; return ss.str(); } -template -void VonMisesFisherChiSquareComponentSplitter::CalculateSplitStatistics(const VMM &vmm, ComponentSplitStatistics &splitStats, const float &mcEstimate, const SampleData *data, const size_t &numData) const +template +void VonMisesFisherChiSquareComponentSplitter::CalculateSplitStatistics(const VMM &vmm, ComponentSplitStatistics &splitStats, const float &mcEstimate, + const SampleData *data, const size_t &numData) const { splitStats.clear(vmm._numComponents); this->UpdateSplitStatistics(vmm, splitStats, mcEstimate, data, numData); } - -template -void VonMisesFisherChiSquareComponentSplitter::PerformSplitting(VMM &vmm, const float &splitThreshold, const float &mcEstimate, const SampleData *data, const size_t &numData, const typename VMMFactory::Configuration factoryCfg, const bool &doPartialRefit, const int &maxSplittingItr) const +template +void VonMisesFisherChiSquareComponentSplitter::PerformSplitting(VMM &vmm, const float &splitThreshold, const float &mcEstimate, const SampleData *data, + const size_t &numData, const typename VMMFactory::Configuration factoryCfg, const bool &doPartialRefit, + const int &maxSplittingItr) const { PartialFittingMask mask; ComponentSplitStatistics splitStatistics; @@ -229,9 +227,9 @@ void VonMisesFisherChiSquareComponentSplitter::PerformSplitting(VMM typename VMMFactory::FittingStatistics vmmFitStats; #ifndef OPENPGL_USE_THREE_SPLIT - while ( vmm._numComponents < VMM::MaxComponents && !stopSplitting) + while (vmm._numComponents < VMM::MaxComponents && !stopSplitting) #else - while ( vmm._numComponents < VMM::MaxComponents-1 && !stopSplitting) + while (vmm._numComponents < VMM::MaxComponents - 1 && !stopSplitting) #endif { stopSplitting = true; @@ -244,18 +242,18 @@ void VonMisesFisherChiSquareComponentSplitter::PerformSplitting(VMM const size_t numComp = vmm._numComponents; for (size_t k = 0; k < numComp; k++) { - if (splitComps[k].chiSquareEst > splitThreshold && vmm._numComponents < VMM::MaxComponents) + if (splitComps[k].chiSquareEst > splitThreshold && vmm._numComponents < VMM::MaxComponents) { - //std::cout << "split[" << k << "]: idx:" << splitComps[k].componentIndex << "\t chi2: " << splitComps[k].chiSquareEst << std::endl; + // std::cout << "split[" << k << "]: idx:" << splitComps[k].componentIndex << "\t chi2: " << splitComps[k].chiSquareEst << std::endl; #ifndef OPENPGL_USE_THREE_SPLIT bool splitSucess = SplitComponent(vmm, splitStatistics, suffStatistics, splitComps[k].componentIndex); mask.setToTrue(splitComps[k].componentIndex); - mask.setToTrue(vmm._numComponents-1); + mask.setToTrue(vmm._numComponents - 1); #else bool splitSucess = SplitComponentIntoThree(vmm, splitStatistics, suffStatistics, splitComps[k].componentIndex); mask.setToTrue(splitComps[k].componentIndex); - mask.setToTrue(vmm._numComponents-2); - mask.setToTrue(vmm._numComponents-1); + mask.setToTrue(vmm._numComponents - 2); + mask.setToTrue(vmm._numComponents - 1); #endif if (splitSucess) { @@ -268,14 +266,14 @@ void VonMisesFisherChiSquareComponentSplitter::PerformSplitting(VMM } } suffStatistics.clear(vmm._numComponents); - //std::cout << "mask: " << mask.toString() << std::endl; - //std::cout << "vmmSplit: " << vmm.toString() << std::endl; - //std::cout << "factoryCfg: " << factoryCfg.toString() << std::endl; - //std::cout << "suffStatistics: " << suffStatistics.toString() << std::endl; + // std::cout << "mask: " << mask.toString() << std::endl; + // std::cout << "vmmSplit: " << vmm.toString() << std::endl; + // std::cout << "factoryCfg: " << factoryCfg.toString() << std::endl; + // std::cout << "suffStatistics: " << suffStatistics.toString() << std::endl; if (doPartialRefit) { vmmFactory.partialUpdateMixture(vmm, mask, suffStatistics, data, numData, factoryCfg, vmmFitStats); - //std::cout << "vmmpartialUpdate: " << vmm.toString() << std::endl; + // std::cout << "vmmpartialUpdate: " << vmm.toString() << std::endl; splitItr++; } else @@ -290,26 +288,28 @@ void VonMisesFisherChiSquareComponentSplitter::PerformSplitting(VMM } } -template -void VonMisesFisherChiSquareComponentSplitter::PerformRecursiveSplitting(VMM &vmm, typename VMMFactory::SufficientStatistics &suffStatistics, const float &splitThreshold, const float &mcEstimate, const SampleData *data, const size_t &numData, const typename VMMFactory::Configuration factoryCfg) const +template +void VonMisesFisherChiSquareComponentSplitter::PerformRecursiveSplitting(VMM &vmm, typename VMMFactory::SufficientStatistics &suffStatistics, + const float &splitThreshold, const float &mcEstimate, const SampleData *data, + const size_t &numData, const typename VMMFactory::Configuration factoryCfg) const { PartialFittingMask mask; ComponentSplitStatistics splitStatistics; SufficientStatistics tempSuffStatistics = suffStatistics; - //bool stopSplitting = false; - //size_t splitItr = 0; + // bool stopSplitting = false; + // size_t splitItr = 0; VMMFactory vmmFactory; typename VMMFactory::FittingStatistics vmmFitStats; - //std::cout << "vmm: " << vmm.toString() << std::endl; + // std::cout << "vmm: " << vmm.toString() << std::endl; int numSplits = -1; #ifndef OPENPGL_USE_THREE_SPLIT - while ( vmm._numComponents < VMM::MaxComponents && numSplits != 0) + while (vmm._numComponents < VMM::MaxComponents && numSplits != 0) #else #endif - //for (size_t j =0; j<1; j++) + // for (size_t j =0; j<1; j++) { numSplits = 0; splitStatistics.clearAll(); @@ -321,17 +321,17 @@ void VonMisesFisherChiSquareComponentSplitter::PerformRecursiveSpli const size_t numComp = vmm._numComponents; for (size_t k = 0; k < numComp; k++) { - if (splitComps[k].chiSquareEst > splitThreshold && vmm._numComponents < VMM::MaxComponents) + if (splitComps[k].chiSquareEst > splitThreshold && vmm._numComponents < VMM::MaxComponents) { #ifndef OPENPGL_USE_THREE_SPLIT bool splitSucess = SplitComponent(vmm, splitStatistics, tempSuffStatistics, splitComps[k].componentIndex); mask.setToTrue(splitComps[k].componentIndex); - mask.setToTrue(vmm._numComponents-1); + mask.setToTrue(vmm._numComponents - 1); #else bool splitSucess = SplitComponentIntoThree(vmm, splitStatistics, tempSuffStatistics, splitComps[k].componentIndex); mask.setToTrue(splitComps[k].componentIndex); - mask.setToTrue(vmm._numComponents-1); - mask.setToTrue(vmm._numComponents-2); + mask.setToTrue(vmm._numComponents - 1); + mask.setToTrue(vmm._numComponents - 2); #endif if (splitSucess) { @@ -347,22 +347,23 @@ void VonMisesFisherChiSquareComponentSplitter::PerformRecursiveSpli { tempSuffStatistics.clear(vmm._numComponents); vmmFactory.partialUpdateMixture(vmm, mask, tempSuffStatistics, data, numData, factoryCfg, vmmFitStats); - //std::cout << "tempSuffStatistics" << std::endl << tempSuffStatistics.toString() << std::endl; + // std::cout << "tempSuffStatistics" << std::endl << tempSuffStatistics.toString() << std::endl; suffStatistics.setNumComponents(vmm._numComponents); suffStatistics.maskedReplace(mask, tempSuffStatistics); } - //std::cout << "vmmpartialUpdate: " << vmm.toString() << std::endl; - //splitItr++; + // std::cout << "vmmpartialUpdate: " << vmm.toString() << std::endl; + // splitItr++; } } -template -ComponentSplitinfo VonMisesFisherChiSquareComponentSplitter::GetProjectedLocalDirections(const VMM &vmm, const size_t &idx, const SampleData *data, const size_t &numData, Vector3 *local2D) const +template +ComponentSplitinfo VonMisesFisherChiSquareComponentSplitter::GetProjectedLocalDirections(const VMM &vmm, const size_t &idx, const SampleData *data, + const size_t &numData, Vector3 *local2D) const { typename VMM::SoftAssignment softAssign; const embree::vfloat zeros(0.f); - //const int cnt = (vmm._numComponents + VMM::VectorSize-1) / VMM::VectorSize; - //size_t validDataCount = 0.0f; + // const int cnt = (vmm._numComponents + VMM::VectorSize-1) / VMM::VectorSize; + // size_t validDataCount = 0.0f; ComponentSplitinfo splitInfo; @@ -375,19 +376,19 @@ ComponentSplitinfo VonMisesFisherChiSquareComponentSplitter::GetPro const SampleData sample = data[n]; pgl_vec3f direction = sample.direction; openpgl::Vector3 sampleDirection(direction.x, direction.y, direction.z); - if (vmm.softAssignment(sampleDirection, softAssign) ) + if (vmm.softAssignment(sampleDirection, softAssign)) { const div_t tmp = div(idx, static_cast(VMM::VectorSize)); const embree::vfloat weight = sample.weight; - //const embree::vfloat samplePDF = sample.pdf; - //const vfloat value = weight * samplePDF; - - - const embree::Vec3< embree::vfloat > localDirection = embree::frame( vmm._meanDirections[tmp.quot] ).inverse() * embree::Vec3< embree::vfloat > (sampleDirection); - //const embree::Vec2< embree::vfloat > localDirection2D = Map3DTo2D< embree::Vec3< embree::vfloat >, embree::Vec2< embree::vfloat >, embree::vfloat >(localDirection); - const Vector2 localDirection2D = Map3DTo2D< Vector3, Vector2, float >(Vector3(localDirection.x[tmp.rem], localDirection.y[tmp.rem], localDirection.z[tmp.rem])); + // const embree::vfloat samplePDF = sample.pdf; + // const vfloat value = weight * samplePDF; + const embree::Vec3 > localDirection = + embree::frame(vmm._meanDirections[tmp.quot]).inverse() * embree::Vec3 >(sampleDirection); + // const embree::Vec2< embree::vfloat > localDirection2D = Map3DTo2D< embree::Vec3< embree::vfloat >, embree::Vec2< + // embree::vfloat >, embree::vfloat >(localDirection); + const Vector2 localDirection2D = Map3DTo2D(Vector3(localDirection.x[tmp.rem], localDirection.y[tmp.rem], localDirection.z[tmp.rem])); const embree::vfloat assignedWeight = softAssign.assignments[tmp.quot] * weight; local2D[n].x = localDirection2D.x; @@ -410,11 +411,13 @@ ComponentSplitinfo VonMisesFisherChiSquareComponentSplitter::GetPro mean /= sumWeights; splitInfo.mean = mean; - splitInfo.covariance.x = covarianceStats.x / sumWeights - mean.x*mean.x; - splitInfo.covariance.y = covarianceStats.y / sumWeights - mean.y*mean.y; - splitInfo.covariance.z = covarianceStats.z / sumWeights - mean.x*mean.y; + splitInfo.covariance.x = covarianceStats.x / sumWeights - mean.x * mean.x; + splitInfo.covariance.y = covarianceStats.y / sumWeights - mean.y * mean.y; + splitInfo.covariance.z = covarianceStats.z / sumWeights - mean.x * mean.y; - float D = embree::sqrt((splitInfo.covariance.x - splitInfo.covariance.y) * (splitInfo.covariance.x - splitInfo.covariance.y) + (splitInfo.covariance.z * splitInfo.covariance.z *4.0f)) * 0.5f; + float D = embree::sqrt((splitInfo.covariance.x - splitInfo.covariance.y) * (splitInfo.covariance.x - splitInfo.covariance.y) + + (splitInfo.covariance.z * splitInfo.covariance.z * 4.0f)) * + 0.5f; splitInfo.eigenValue0 = (splitInfo.covariance.x + splitInfo.covariance.y) * 0.5; splitInfo.eigenValue0 += D; @@ -430,37 +433,39 @@ ComponentSplitinfo VonMisesFisherChiSquareComponentSplitter::GetPro splitInfo.eigenVector0 /= embree::sqrt(splitInfo.eigenVector0.x * splitInfo.eigenVector0.x + splitInfo.eigenVector0.y * splitInfo.eigenVector0.y); splitInfo.eigenVector1 /= embree::sqrt(splitInfo.eigenVector1.x * splitInfo.eigenVector1.x + splitInfo.eigenVector1.y * splitInfo.eigenVector1.y); #ifdef OPENPGL_SHOW_PRINT_OUTS - std::cout << "split: " << "\tmean: " << splitInfo.mean.x << ", \t " << splitInfo.mean.y<< "\t covariance: " << splitInfo.covariance.x << ", \t " << splitInfo.covariance.y << ", \t " << splitInfo.covariance.z << std::endl; - std::cout << "eigen: " << "\tevalue0: " << splitInfo.eigenValue0 << "\teVec0: " << splitInfo.eigenVector0.x << ", \t " << splitInfo.eigenVector0.y << "\tevalue1: " << splitInfo.eigenValue1 << "\teVec1: " << splitInfo.eigenVector1.x << ", \t " << splitInfo.eigenVector1.y << std::endl; + std::cout << "split: " << "\tmean: " << splitInfo.mean.x << ", \t " << splitInfo.mean.y << "\t covariance: " << splitInfo.covariance.x << ", \t " << splitInfo.covariance.y + << ", \t " << splitInfo.covariance.z << std::endl; + std::cout << "eigen: " << "\tevalue0: " << splitInfo.eigenValue0 << "\teVec0: " << splitInfo.eigenVector0.x << ", \t " << splitInfo.eigenVector0.y + << "\tevalue1: " << splitInfo.eigenValue1 << "\teVec1: " << splitInfo.eigenVector1.x << ", \t " << splitInfo.eigenVector1.y << std::endl; #endif return splitInfo; } - -template -void VonMisesFisherChiSquareComponentSplitter::UpdateSplitStatistics(const VMM &vmm, ComponentSplitStatistics &splitStats, const float &mcEstimate, const SampleData *data, const size_t &numData) const +template +void VonMisesFisherChiSquareComponentSplitter::UpdateSplitStatistics(const VMM &vmm, ComponentSplitStatistics &splitStats, const float &mcEstimate, + const SampleData *data, const size_t &numData) const { - //std::cout << "UpdateSplitStatistics" << std::endl; + // std::cout << "UpdateSplitStatistics" << std::endl; OPENPGL_ASSERT(vmm._numComponents == splitStats.numComponents); typename VMM::SoftAssignment softAssign; const embree::vfloat zeros(0.f); - const int cnt = (splitStats.numComponents + VMM::VectorSize-1) / VMM::VectorSize; - //size_t validDataCount = 0.0f; + const int cnt = (splitStats.numComponents + VMM::VectorSize - 1) / VMM::VectorSize; + // size_t validDataCount = 0.0f; for (size_t n = 0; n < numData; n++) { const SampleData sample = data[n]; pgl_vec3f direction = sample.direction; const openpgl::Vector3 sampleDirection(direction.x, direction.y, direction.z); - if (vmm.softAssignment(sampleDirection, softAssign) ) + if (vmm.softAssignment(sampleDirection, softAssign)) { const embree::vfloat weight = sample.weight; const embree::vfloat samplePDF = sample.pdf; - const embree::vfloat value = weight * samplePDF; - //std::cout << "data[" << n << "]: " << "value: " << value << "\t samplePDF: " << samplePDF; - for (size_t k =0; k < cnt; k++) + const embree::vfloat value = weight * samplePDF; + // std::cout << "data[" << n << "]: " << "value: " << value << "\t samplePDF: " << samplePDF; + for (size_t k = 0; k < cnt; k++) { OPENPGL_ASSERT(embree::all(embree::isvalid(splitStats.splitMeans[k].x))); OPENPGL_ASSERT(embree::all(embree::isvalid(splitStats.splitMeans[k].y))); @@ -471,43 +476,47 @@ void VonMisesFisherChiSquareComponentSplitter::UpdateSplitStatistic embree::vfloat vmfPDF = softAssign.assignments[k] * softAssign.pdf; embree::vfloat partialValuePDF = vmfPDF * value; partialValuePDF /= (mcEstimate * softAssign.pdf); - //partialValuePDF /= vmm._weights[k] * mcEstimate; - //std::cout << "\tweights: " << vmm._weights[k] << "\t assign: " << softAssign.assignments[k] << "\t pdf: " << softAssign.pdf << std::endl; - //std::cout << "\tpvPDF: " << partialValuePDF << "\t vmfPDF: " << vmfPDF << std::endl; + // partialValuePDF /= vmm._weights[k] * mcEstimate; + // std::cout << "\tweights: " << vmm._weights[k] << "\t assign: " << softAssign.assignments[k] << "\t pdf: " << softAssign.pdf << std::endl; + // std::cout << "\tpvPDF: " << partialValuePDF << "\t vmfPDF: " << vmfPDF << std::endl; - embree::vfloat chiSquareEst = value *value * vmfPDF; + embree::vfloat chiSquareEst = value * value * vmfPDF; chiSquareEst /= mcEstimate * mcEstimate * softAssign.pdf * softAssign.pdf; - //chiSquareEst *= chiSquareEst; + // chiSquareEst *= chiSquareEst; chiSquareEst -= 2.0f * partialValuePDF; chiSquareEst += vmfPDF; chiSquareEst /= samplePDF; - chiSquareEst = select(softAssign.assignments[k] > 0.f , chiSquareEst, zeros); + chiSquareEst = select(softAssign.assignments[k] > 0.f, chiSquareEst, zeros); splitStats.sumAssignedSamples[k] += softAssign.assignments[k]; // incremental updated of the MC chiSquare estimate splitStats.numSamples[k] += 1.0f; splitStats.chiSquareMCEstimates[k] += (chiSquareEst - splitStats.chiSquareMCEstimates[k]) / splitStats.numSamples[k]; - const embree::Vec3< embree::vfloat > localDirection = embree::frame( vmm._meanDirections[k] ).inverse() * embree::Vec3< embree::vfloat > (sampleDirection); - const embree::Vec2< embree::vfloat > localDirection2D(localDirection.x, localDirection.y); + const embree::Vec3 > localDirection = + embree::frame(vmm._meanDirections[k]).inverse() * embree::Vec3 >(sampleDirection); + const embree::Vec2 > localDirection2D(localDirection.x, localDirection.y); const embree::vfloat assignedWeight = softAssign.assignments[k] * weight; - //const vfloat assignedWeight = softAssign.assignments[k] * weight * weight; + // const vfloat assignedWeight = softAssign.assignments[k] * weight * weight; splitStats.sumWeights[k] += assignedWeight; -// const vfloat incWeight = select(splitStats.sumWeights[k] > 0.0f, assignedWeight / splitStats.sumWeights[k], zeros); + // const vfloat incWeight = select(splitStats.sumWeights[k] > 0.0f, assignedWeight / splitStats.sumWeights[k], zeros); #ifdef OPENPGL_ZERO_MEAN - splitStats.splitMeans[k] += embree::Vec2< embree::vfloat >(0.0f); + splitStats.splitMeans[k] += embree::Vec2 >(0.0f); splitStats.splitWeightedSampleCovariances[k].x += assignedWeight * (localDirection2D.x * localDirection2D.x); splitStats.splitWeightedSampleCovariances[k].y += assignedWeight * (localDirection2D.y * localDirection2D.y); splitStats.splitWeightedSampleCovariances[k].z += assignedWeight * (localDirection2D.x * localDirection2D.y); #else - const Vec2< vfloat > previousSplitMeans = splitStats.splitMeans[k]; - splitStats.splitMeans[k] += incWeight * ( localDirection2D - splitStats.splitMeans[k]); - splitStats.splitWeightedSampleCovariances[k].x += assignedWeight * ((localDirection2D.x - previousSplitMeans.x) * (localDirection2D.x - splitStats.splitMeans[k].x)); - splitStats.splitWeightedSampleCovariances[k].y += assignedWeight * ((localDirection2D.y - previousSplitMeans.y) * (localDirection2D.y - splitStats.splitMeans[k].y)); - splitStats.splitWeightedSampleCovariances[k].z += assignedWeight * ((localDirection2D.x - previousSplitMeans.x) * (localDirection2D.y - splitStats.splitMeans[k].y)); + const Vec2 > previousSplitMeans = splitStats.splitMeans[k]; + splitStats.splitMeans[k] += incWeight * (localDirection2D - splitStats.splitMeans[k]); + splitStats.splitWeightedSampleCovariances[k].x += + assignedWeight * ((localDirection2D.x - previousSplitMeans.x) * (localDirection2D.x - splitStats.splitMeans[k].x)); + splitStats.splitWeightedSampleCovariances[k].y += + assignedWeight * ((localDirection2D.y - previousSplitMeans.y) * (localDirection2D.y - splitStats.splitMeans[k].y)); + splitStats.splitWeightedSampleCovariances[k].z += + assignedWeight * ((localDirection2D.x - previousSplitMeans.x) * (localDirection2D.y - splitStats.splitMeans[k].y)); #endif OPENPGL_ASSERT(embree::all(embree::isvalid(assignedWeight))); OPENPGL_ASSERT(embree::all(embree::isvalid(splitStats.splitMeans[k].x))); @@ -515,24 +524,22 @@ void VonMisesFisherChiSquareComponentSplitter::UpdateSplitStatistic OPENPGL_ASSERT(embree::all(embree::isvalid(splitStats.splitWeightedSampleCovariances[k].x))); OPENPGL_ASSERT(embree::all(embree::isvalid(splitStats.splitWeightedSampleCovariances[k].y))); OPENPGL_ASSERT(embree::all(embree::isvalid(splitStats.splitWeightedSampleCovariances[k].z))); - //splitStats.sumWeights[k] += assignedWeight; + // splitStats.sumWeights[k] += assignedWeight; } - //validDataCount++; - //std::cout << std::endl; + // validDataCount++; + // std::cout << std::endl; } } - //splitStats.numSamplesOld += validDataCount; - //splitStats.mcEstimate += mcEstimate; + // splitStats.numSamplesOld += validDataCount; + // splitStats.mcEstimate += mcEstimate; } - -template +template bool VonMisesFisherChiSquareComponentSplitter::SplitComponent(VMM &vmm, ComponentSplitStatistics &splitStats, SufficientStatistics &suffStats, const size_t idx) const { ComponentSplitinfo splitInfo; const div_t tmpK = div(idx, static_cast(VMM::VectorSize)); - float numAssignedSamples = splitStats.sumAssignedSamples[tmpK.quot][tmpK.rem]; float inv_sumWeights = embree::rcp(splitStats.sumWeights[tmpK.quot][tmpK.rem]); @@ -543,7 +550,9 @@ bool VonMisesFisherChiSquareComponentSplitter::SplitComponent(VMM & splitInfo.covariance.y = splitStats.splitWeightedSampleCovariances[tmpK.quot].y[tmpK.rem] * inv_sumWeights; splitInfo.covariance.z = splitStats.splitWeightedSampleCovariances[tmpK.quot].z[tmpK.rem] * inv_sumWeights; - float D = embree::sqrt((splitInfo.covariance.x - splitInfo.covariance.y) * (splitInfo.covariance.x - splitInfo.covariance.y) + (splitInfo.covariance.z * splitInfo.covariance.z *4.0f)) * 0.5f; + float D = embree::sqrt((splitInfo.covariance.x - splitInfo.covariance.y) * (splitInfo.covariance.x - splitInfo.covariance.y) + + (splitInfo.covariance.z * splitInfo.covariance.z * 4.0f)) * + 0.5f; splitInfo.eigenValue0 = (splitInfo.covariance.x + splitInfo.covariance.y) * 0.5; splitInfo.eigenValue0 += D; @@ -558,15 +567,16 @@ bool VonMisesFisherChiSquareComponentSplitter::SplitComponent(VMM & splitInfo.eigenVector0 /= embree::sqrt(splitInfo.eigenVector0.x * splitInfo.eigenVector0.x + splitInfo.eigenVector0.y * splitInfo.eigenVector0.y); splitInfo.eigenVector1 /= embree::sqrt(splitInfo.eigenVector1.x * splitInfo.eigenVector1.x + splitInfo.eigenVector1.y * splitInfo.eigenVector1.y); -/* */ - //std::cout << "D: " << D << std::endl; - //std::cout << "sumWeights: " << splitStats.sumWeights[tmpK.quot][tmpK.rem] << "\t inSumWeights: " << inv_sumWeights << std::endl; - //std::cout << "splitMean: " << splitInfo.mean << "\t splitCovariance: " << splitInfo.covariance << std::endl; + /* */ + // std::cout << "D: " << D << std::endl; + // std::cout << "sumWeights: " << splitStats.sumWeights[tmpK.quot][tmpK.rem] << "\t inSumWeights: " << inv_sumWeights << std::endl; + // std::cout << "splitMean: " << splitInfo.mean << "\t splitCovariance: " << splitInfo.covariance << std::endl; - //std::cout << "splitCovariancesRaw: " << splitStats.splitCovariances[tmpK.quot].x[tmpK.rem] << "\t" << splitStats.splitCovariances[tmpK.quot].y[tmpK.rem] << "\t" << splitStats.splitCovariances[tmpK.quot].z[tmpK.rem] << std::endl; -// std::cout << "eigenValue0: " << splitInfo.eigenValue0 << "\t eigenVector0: " << splitInfo.eigenVector0 << std::endl; -// std::cout << "eigenValue1: " << splitInfo.eigenValue1 << "\t eigenVector1: " << splitInfo.eigenVector1 << std::endl; -/**/ + // std::cout << "splitCovariancesRaw: " << splitStats.splitCovariances[tmpK.quot].x[tmpK.rem] << "\t" << splitStats.splitCovariances[tmpK.quot].y[tmpK.rem] << "\t" << + // splitStats.splitCovariances[tmpK.quot].z[tmpK.rem] << std::endl; + // std::cout << "eigenValue0: " << splitInfo.eigenValue0 << "\t eigenVector0: " << splitInfo.eigenVector0 << std::endl; + // std::cout << "eigenValue1: " << splitInfo.eigenValue1 << "\t eigenVector1: " << splitInfo.eigenVector1 << std::endl; + /**/ float weight = vmm._weights[tmpK.quot][tmpK.rem]; float meanCosine = vmm._meanCosines[tmpK.quot][tmpK.rem]; @@ -577,9 +587,7 @@ bool VonMisesFisherChiSquareComponentSplitter::SplitComponent(VMM & return false; } - Vector3 meanDirection = Vector3(vmm._meanDirections[tmpK.quot].x[tmpK.rem], - vmm._meanDirections[tmpK.quot].y[tmpK.rem], - vmm._meanDirections[tmpK.quot].z[tmpK.rem]); + Vector3 meanDirection = Vector3(vmm._meanDirections[tmpK.quot].x[tmpK.rem], vmm._meanDirections[tmpK.quot].y[tmpK.rem], vmm._meanDirections[tmpK.quot].z[tmpK.rem]); float newWeight0 = weight * 0.5f; float newWeight1 = newWeight0; @@ -588,17 +596,17 @@ bool VonMisesFisherChiSquareComponentSplitter::SplitComponent(VMM & Vector3 meanDirection1 = meanDirection; float newMeanCosine0 = meanCosine; - float newMeanCosine1 = meanCosine*meanCosine; + float newMeanCosine1 = meanCosine * meanCosine; if (D > 1e-8f) { Vector2 meanDir2D0 = splitInfo.mean + (splitInfo.eigenVector0 * splitInfo.eigenValue0 * 0.5f); - meanDirection0 = embree::frame(meanDirection) * Map2DTo3D(meanDir2D0); + meanDirection0 = embree::frame(meanDirection) * Map2DTo3D(meanDir2D0); newMeanCosine0 = meanCosine / std::abs(dot(meanDirection, meanDirection0)); - - //TODO: further investigate: - //newMeanCosine0 = meanCosine / dot(meanDirection, meanDirection0); - + + // TODO: further investigate: + // newMeanCosine0 = meanCosine / dot(meanDirection, meanDirection0); + OPENPGL_ASSERT(meanCosine >= 0.f); OPENPGL_ASSERT(std::abs(dot(meanDirection, meanDirection0)) > 0.f); OPENPGL_ASSERT(newMeanCosine0 >= 0.f); @@ -610,25 +618,29 @@ bool VonMisesFisherChiSquareComponentSplitter::SplitComponent(VMM & meanDirection1 = embree::frame(meanDirection) * Map2DTo3D(meanDir2D1); #ifdef OPENPGL_SHOW_PRINT_OUTS - //std::cout << "meanCosine: " << meanCosine << "\t kappa: " << kappa << "\t newMeanCosine: " << newMeanCosine0 << " \t newKkappa: " << newKkappa0 << std::endl; - //std::cout << "localMeanDirection0: " << Map2DTo3D(meanDir2D0) << "\t meanDirection0: " << meanDirection0 << "\t meanCosine: " << meanCosine << " \t costheta0: " << dot(meanDirection, meanDirection0) << std::endl; - //std::cout << "localMeanDirection1: " << Map2DTo3D(meanDir2D1) << "\t meanDirection1: " << meanDirection1 << "\t meanCosine: " << meanCosine << " \t costheta1: " << dot(meanDirection, meanDirection1) << std::endl; - //std::cout << "eigenValue0: " << splitInfo.eigenValue0 << "\t eigenVector0: " << splitInfo.eigenVector0 << std::endl; - //std::cout << "eigenValue1: " << splitInfo.eigenValue1 << "\t eigenVector1: " << splitInfo.eigenVector1 << std::endl; - std::cout << "D: " << D << "\t idx: " << idx << " \t assignedSamples: " << numAssignedSamples <(meanDir2D0) << "\t meanDirection0: " << meanDirection0 << "\t meanCosine: " << meanCosine << " + // \t costheta0: " << dot(meanDirection, meanDirection0) << std::endl; std::cout << "localMeanDirection1: " << Map2DTo3D(meanDir2D1) << "\t + // meanDirection1: " << meanDirection1 << "\t meanCosine: " << meanCosine << " \t costheta1: " << dot(meanDirection, meanDirection1) << std::endl; std::cout << + // "eigenValue0: " << splitInfo.eigenValue0 << "\t eigenVector0: " << splitInfo.eigenVector0 << std::endl; std::cout << "eigenValue1: " << splitInfo.eigenValue1 << "\t + // eigenVector1: " << splitInfo.eigenVector1 << std::endl; + std::cout << "D: " << D << "\t idx: " << idx << " \t assignedSamples: " << numAssignedSamples << std::endl; + // std::cout << "kappa: " << kappa << " \t newKkappa: " << newKkappa0 << " \t costheta0: " << dot(meanDirection, meanDirection0) << "\t angle: " << + // std::acos(dot(meanDirection, meanDirection0)) * 180.0f / M_PI_F<< std::endl; #endif } else { #ifdef OPENPGL_SHOW_PRINT_OUTS - std::cout << "!!!! D: " << D << "\t idx: " << idx << " \t assignedSamples: " << numAssignedSamples <::SplitComponent(VMM & splitStats.splitWeightedSampleCovariances[tmpJ.quot].y[tmpJ.rem] = 0.0f; splitStats.splitWeightedSampleCovariances[tmpJ.quot].z[tmpJ.rem] = 0.0f; - splitStats.numComponents = K +1; + splitStats.numComponents = K + 1; return true; } -template -bool VonMisesFisherChiSquareComponentSplitter::SplitComponentIntoThree(VMM &vmm, ComponentSplitStatistics &splitStats, SufficientStatistics &suffStats, const size_t idx) const +template +bool VonMisesFisherChiSquareComponentSplitter::SplitComponentIntoThree(VMM &vmm, ComponentSplitStatistics &splitStats, SufficientStatistics &suffStats, + const size_t idx) const { ComponentSplitinfo splitInfo; const div_t tmpK = div(idx, static_cast(VMM::VectorSize)); - float numAssignedSamples = splitStats.sumAssignedSamples[tmpK.quot][tmpK.rem]; float inv_sumWeights = rcp(splitStats.sumWeights[tmpK.quot][tmpK.rem]); @@ -683,7 +695,9 @@ bool VonMisesFisherChiSquareComponentSplitter::SplitComponentIntoTh splitInfo.covariance.y = splitStats.splitWeightedSampleCovariances[tmpK.quot].y[tmpK.rem] * inv_sumWeights; splitInfo.covariance.z = splitStats.splitWeightedSampleCovariances[tmpK.quot].z[tmpK.rem] * inv_sumWeights; - float D = embree::sqrt((splitInfo.covariance.x - splitInfo.covariance.y) * (splitInfo.covariance.x - splitInfo.covariance.y) + (splitInfo.covariance.z * splitInfo.covariance.z *4.0f)) * 0.5f; + float D = embree::sqrt((splitInfo.covariance.x - splitInfo.covariance.y) * (splitInfo.covariance.x - splitInfo.covariance.y) + + (splitInfo.covariance.z * splitInfo.covariance.z * 4.0f)) * + 0.5f; splitInfo.eigenValue0 = (splitInfo.covariance.x + splitInfo.covariance.y) * 0.5; splitInfo.eigenValue0 += D; @@ -698,15 +712,16 @@ bool VonMisesFisherChiSquareComponentSplitter::SplitComponentIntoTh splitInfo.eigenVector0 /= embree::sqrt(splitInfo.eigenVector0.x * splitInfo.eigenVector0.x + splitInfo.eigenVector0.y * splitInfo.eigenVector0.y); splitInfo.eigenVector1 /= embree::sqrt(splitInfo.eigenVector1.x * splitInfo.eigenVector1.x + splitInfo.eigenVector1.y * splitInfo.eigenVector1.y); -/* */ - //std::cout << "D: " << D << std::endl; - //std::cout << "sumWeights: " << splitStats.sumWeights[tmpK.quot][tmpK.rem] << "\t inSumWeights: " << inv_sumWeights << std::endl; - //std::cout << "splitMean: " << splitInfo.mean << "\t splitCovariance: " << splitInfo.covariance << std::endl; + /* */ + // std::cout << "D: " << D << std::endl; + // std::cout << "sumWeights: " << splitStats.sumWeights[tmpK.quot][tmpK.rem] << "\t inSumWeights: " << inv_sumWeights << std::endl; + // std::cout << "splitMean: " << splitInfo.mean << "\t splitCovariance: " << splitInfo.covariance << std::endl; - //std::cout << "splitCovariancesRaw: " << splitStats.splitCovariances[tmpK.quot].x[tmpK.rem] << "\t" << splitStats.splitCovariances[tmpK.quot].y[tmpK.rem] << "\t" << splitStats.splitCovariances[tmpK.quot].z[tmpK.rem] << std::endl; -// std::cout << "eigenValue0: " << splitInfo.eigenValue0 << "\t eigenVector0: " << splitInfo.eigenVector0 << std::endl; -// std::cout << "eigenValue1: " << splitInfo.eigenValue1 << "\t eigenVector1: " << splitInfo.eigenVector1 << std::endl; -/**/ + // std::cout << "splitCovariancesRaw: " << splitStats.splitCovariances[tmpK.quot].x[tmpK.rem] << "\t" << splitStats.splitCovariances[tmpK.quot].y[tmpK.rem] << "\t" << + // splitStats.splitCovariances[tmpK.quot].z[tmpK.rem] << std::endl; + // std::cout << "eigenValue0: " << splitInfo.eigenValue0 << "\t eigenVector0: " << splitInfo.eigenVector0 << std::endl; + // std::cout << "eigenValue1: " << splitInfo.eigenValue1 << "\t eigenVector1: " << splitInfo.eigenVector1 << std::endl; + /**/ float weight = vmm._weights[tmpK.quot][tmpK.rem]; float meanCosine = vmm._meanCosines[tmpK.quot][tmpK.rem]; @@ -717,13 +732,11 @@ bool VonMisesFisherChiSquareComponentSplitter::SplitComponentIntoTh return false; } - Vector3 meanDirection = Vector3(vmm._meanDirections[tmpK.quot].x[tmpK.rem], - vmm._meanDirections[tmpK.quot].y[tmpK.rem], - vmm._meanDirections[tmpK.quot].z[tmpK.rem]); + Vector3 meanDirection = Vector3(vmm._meanDirections[tmpK.quot].x[tmpK.rem], vmm._meanDirections[tmpK.quot].y[tmpK.rem], vmm._meanDirections[tmpK.quot].z[tmpK.rem]); float distance = vmm._distances[tmpK.quot][tmpK.rem]; - float newWeight0 = weight *embree::rcp(3.0f); + float newWeight0 = weight * embree::rcp(3.0f); float newWeight1 = newWeight0; float newWeight2 = newWeight0; @@ -731,57 +744,61 @@ bool VonMisesFisherChiSquareComponentSplitter::SplitComponentIntoTh Vector3 meanDirection1 = meanDirection; float newMeanCosine0 = meanCosine; - float newMeanCosine1 = meanCosine*meanCosine; + float newMeanCosine1 = meanCosine * meanCosine; - float newKkappa0 = MeanCosineToKappa (newMeanCosine0); - float newKkappa1 = MeanCosineToKappa (newMeanCosine1); + float newKkappa0 = MeanCosineToKappa(newMeanCosine0); + float newKkappa1 = MeanCosineToKappa(newMeanCosine1); if (D > 1e-8f) { Vector2 meanDir2D0 = splitInfo.mean + (splitInfo.eigenVector0 * splitInfo.eigenValue0 * 1.0f); - meanDirection0 = embree::frame(meanDirection) * Map2DTo3D(meanDir2D0); + meanDirection0 = embree::frame(meanDirection) * Map2DTo3D(meanDir2D0); newMeanCosine0 = meanCosine / dot(meanDirection, meanDirection0); // ensure that the new mean cosine is in a valid range (i.e., < 1.0 and < the mean cosine of max kappa) newMeanCosine0 = std::min(newMeanCosine0, KappaToMeanCosine(OPENPGL_MAX_KAPPA)); newMeanCosine1 = newMeanCosine0; - newKkappa0 = MeanCosineToKappa (newMeanCosine0); + newKkappa0 = MeanCosineToKappa(newMeanCosine0); newKkappa1 = newKkappa0; Vector2 meanDir2D1 = splitInfo.mean - (splitInfo.eigenVector0 * splitInfo.eigenValue0 * 1.0f); meanDirection1 = embree::frame(meanDirection) * Map2DTo3D(meanDir2D1); - //float meanCosine1 = meanCosine / meanDirection0.z; - //float kappa1 = MeanCosineToKappa (meanCosine1); + // float meanCosine1 = meanCosine / meanDirection0.z; + // float kappa1 = MeanCosineToKappa (meanCosine1); #ifdef OPENPGL_SHOW_PRINT_OUTS - //std::cout << "meanCosine: " << meanCosine << "\t kappa: " << kappa << "\t newMeanCosine: " << newMeanCosine0 << " \t newKkappa: " << newKkappa0 << std::endl; - //std::cout << "localMeanDirection0: " << Map2DTo3D(meanDir2D0) << "\t meanDirection0: " << meanDirection0 << "\t meanCosine: " << meanCosine << " \t costheta0: " << dot(meanDirection, meanDirection0) << std::endl; - //std::cout << "localMeanDirection1: " << Map2DTo3D(meanDir2D1) << "\t meanDirection1: " << meanDirection1 << "\t meanCosine: " << meanCosine << " \t costheta1: " << dot(meanDirection, meanDirection1) << std::endl; - //std::cout << "eigenValue0: " << splitInfo.eigenValue0 << "\t eigenVector0: " << splitInfo.eigenVector0 << std::endl; - //std::cout << "eigenValue1: " << splitInfo.eigenValue1 << "\t eigenVector1: " << splitInfo.eigenVector1 << std::endl; - std::cout << "D: " << D << "\t idx: " << idx << " \t assignedSamples: " << numAssignedSamples <(meanDir2D0) << "\t meanDirection0: " << meanDirection0 << "\t meanCosine: " << meanCosine << " + // \t costheta0: " << dot(meanDirection, meanDirection0) << std::endl; std::cout << "localMeanDirection1: " << Map2DTo3D(meanDir2D1) << "\t + // meanDirection1: " << meanDirection1 << "\t meanCosine: " << meanCosine << " \t costheta1: " << dot(meanDirection, meanDirection1) << std::endl; std::cout << + // "eigenValue0: " << splitInfo.eigenValue0 << "\t eigenVector0: " << splitInfo.eigenVector0 << std::endl; std::cout << "eigenValue1: " << splitInfo.eigenValue1 << "\t + // eigenVector1: " << splitInfo.eigenVector1 << std::endl; + std::cout << "D: " << D << "\t idx: " << idx << " \t assignedSamples: " << numAssignedSamples << std::endl; + std::cout << "kappa: " << kappa << " \t newKkappa: " << newKkappa0 << " \t costheta0: " << dot(meanDirection, meanDirection0) + << "\t angle: " << std::acos(dot(meanDirection, meanDirection0)) * 180.0f / M_PI_F << std::endl; #endif } else { #ifdef OPENPGL_SHOW_PRINT_OUTS - std::cout << "!!!! D: " << D << "\t idx: " << idx << " \t assignedSamples: " << numAssignedSamples <(VMM::VectorSize)); + // vmm.swapComponents(K-1, idx); + // suffStats.swapComponentStats(K-1, idx); + // const div_t tmpI = div(K-1, static_cast(VMM::VectorSize)); const div_t tmpI = tmpK; const div_t tmpJ = div(K, static_cast(VMM::VectorSize)); - const div_t tmpL = div(K+1, static_cast(VMM::VectorSize)); + const div_t tmpL = div(K + 1, static_cast(VMM::VectorSize)); vmm._weights[tmpI.quot][tmpI.rem] = newWeight0; vmm._meanCosines[tmpI.quot][tmpI.rem] = newMeanCosine0; @@ -870,8 +887,8 @@ bool VonMisesFisherChiSquareComponentSplitter::SplitComponentIntoTh return true; } -template -void VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::serialize(std::ostream& stream) const +template +void VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::serialize(std::ostream &stream) const { serializeFloatVectors(stream, chiSquareMCEstimates); serializeVec2Vectors(stream, splitMeans); @@ -879,11 +896,11 @@ void VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatis serializeFloatVectors(stream, numSamples); serializeFloatVectors(stream, sumWeights); serializeFloatVectors(stream, sumAssignedSamples); - stream.write(reinterpret_cast(&numComponents), sizeof(size_t)); + stream.write(reinterpret_cast(&numComponents), sizeof(size_t)); } -template -void VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::deserialize(std::istream& stream) +template +void VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::deserialize(std::istream &stream) { deserializeFloatVectors(stream, chiSquareMCEstimates); deserializeVec2Vectors(stream, splitMeans); @@ -891,17 +908,17 @@ void VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatis deserializeFloatVectors(stream, numSamples); deserializeFloatVectors(stream, sumWeights); deserializeFloatVectors(stream, sumAssignedSamples); - stream.read(reinterpret_cast(&numComponents), sizeof(size_t)); + stream.read(reinterpret_cast(&numComponents), sizeof(size_t)); } -template +template bool VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::isValid() const { bool valid = true; - + embree::vbool validVec(true); - const int cnt = (VMM::MaxComponents + VMM::VectorSize-1) / VMM::VectorSize; - for (size_t k =0; k < cnt; k++) + const int cnt = (VMM::MaxComponents + VMM::VectorSize - 1) / VMM::VectorSize; + for (size_t k = 0; k < cnt; k++) { validVec &= embree::isvalid(splitMeans[k].x); validVec &= embree::isvalid(splitMeans[k].y); @@ -927,7 +944,6 @@ bool VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatis validVec &= embree::isvalid(numSamples[k]); validVec &= numSamples[k] >= 0.0f; OPENPGL_ASSERT(embree::any(validVec)); - } valid = valid && embree::any(validVec); @@ -939,72 +955,71 @@ bool VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatis return valid; } -template -bool VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::operator==(const ComponentSplitStatistics& b) const +template +bool VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::operator==(const ComponentSplitStatistics &b) const { bool equal = true; - if(numComponents != b.numComponents) + if (numComponents != b.numComponents) { - equal = false; + equal = false; } - for(int k = 0; k < VMM::NumVectors;k++) + for (int k = 0; k < VMM::NumVectors; k++) { - - if( embree::any(chiSquareMCEstimates[k] != b.chiSquareMCEstimates[k]) || - embree::any(splitMeans[k].x != b.splitMeans[k].x) || - embree::any(splitMeans[k].y != b.splitMeans[k].y) || - embree::any(splitWeightedSampleCovariances[k].x != b.splitWeightedSampleCovariances[k].x) || - embree::any(splitWeightedSampleCovariances[k].y != b.splitWeightedSampleCovariances[k].y) || - embree::any(splitWeightedSampleCovariances[k].z != b.splitWeightedSampleCovariances[k].z) || - embree::any(numSamples[k] != b.numSamples[k]) || - embree::any(sumWeights[k] != b.sumWeights[k]) || - embree::any(sumAssignedSamples[k] != b.sumAssignedSamples[k])) + if (embree::any(chiSquareMCEstimates[k] != b.chiSquareMCEstimates[k]) || embree::any(splitMeans[k].x != b.splitMeans[k].x) || + embree::any(splitMeans[k].y != b.splitMeans[k].y) || embree::any(splitWeightedSampleCovariances[k].x != b.splitWeightedSampleCovariances[k].x) || + embree::any(splitWeightedSampleCovariances[k].y != b.splitWeightedSampleCovariances[k].y) || + embree::any(splitWeightedSampleCovariances[k].z != b.splitWeightedSampleCovariances[k].z) || embree::any(numSamples[k] != b.numSamples[k]) || + embree::any(sumWeights[k] != b.sumWeights[k]) || embree::any(sumAssignedSamples[k] != b.sumAssignedSamples[k])) { equal = false; } - } return equal; } -template +template Vector2 VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::getSplitMean(const size_t &idx) const { const div_t tmp = div(idx, static_cast(VMM::VectorSize)); return Vector2(splitMeans[tmp.quot].x[tmp.rem], splitMeans[tmp.quot].y[tmp.rem]); } -template +template Vector3 VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::getSplitCovariance(const size_t &idx) const { const div_t tmp = div(idx, static_cast(VMM::VectorSize)); - Vector3 covariance(splitWeightedSampleCovariances[tmp.quot].x[tmp.rem], splitWeightedSampleCovariances[tmp.quot].y[tmp.rem], splitWeightedSampleCovariances[tmp.quot].z[tmp.rem]); + Vector3 covariance(splitWeightedSampleCovariances[tmp.quot].x[tmp.rem], splitWeightedSampleCovariances[tmp.quot].y[tmp.rem], + splitWeightedSampleCovariances[tmp.quot].z[tmp.rem]); covariance /= sumWeights[tmp.quot][tmp.rem]; return covariance; } -template -void VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::mergeComponentStats(const size_t &idxI, const size_t &idxJ, const float &weightI, const Vector3 &meanDirectionI, const float &weightJ, const Vector3 &meanDirectionJ, const float &weightK, const Vector3 &meanDirectionK) +template +void VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::mergeComponentStats(const size_t &idxI, const size_t &idxJ, const float &weightI, + const Vector3 &meanDirectionI, const float &weightJ, + const Vector3 &meanDirectionJ, const float &weightK, + const Vector3 &meanDirectionK) { // TODO: check if numSamples or sumWeights are zero for one of the merge components - //std::cout << "mergeComponentStats: " << "\tidxI: " << idxI << "\tidxJ: " << idxJ << "\tweightI: " << weightI << "\tmeanDirectionI: " << meanDirectionI<< "\tweightJ: " << weightJ << "\tmeanDirectionJ: " << meanDirectionJ<< "\tweightK: " << weightK << "\tmeanDirectionK: " << meanDirectionK << std::endl; + // std::cout << "mergeComponentStats: " << "\tidxI: " << idxI << "\tidxJ: " << idxJ << "\tweightI: " << weightI << "\tmeanDirectionI: " << meanDirectionI<< "\tweightJ: " << + // weightJ << "\tmeanDirectionJ: " << meanDirectionJ<< "\tweightK: " << weightK << "\tmeanDirectionK: " << meanDirectionK << std::endl; // EM algorithms for Gaussian mixtures with split-and-merge operation const div_t tmpI = div(idxI, static_cast(VMM::VectorSize)); const div_t tmpJ = div(idxJ, static_cast(VMM::VectorSize)); - const div_t tmpL = div( numComponents-1, VMM::VectorSize); + const div_t tmpL = div(numComponents - 1, VMM::VectorSize); - auto transformK = embree::frame( meanDirectionK ); + auto transformK = embree::frame(meanDirectionK); auto inv_transformK = transformK.inverse(); #ifdef OPENPGL_ZERO_MEAN Vector3 meanDirectionI3D = meanDirectionI; Vector3 meanDirectionJ3D = meanDirectionJ; #else - auto transformI = embree::frame( meanDirectionI ); - auto transformJ = embree::frame( meanDirectionJ ); + auto transformI = embree::frame(meanDirectionI); + auto transformJ = embree::frame(meanDirectionJ); Vector2 meanDirection2DI = Vector2(splitMeans[tmpI.quot].x[tmpI.rem], splitMeans[tmpI.quot].y[tmpI.rem]); Vector2 meanDirection2DJ = Vector2(splitMeans[tmpJ.quot].x[tmpJ.rem], splitMeans[tmpJ.quot].y[tmpJ.rem]); @@ -1013,8 +1028,8 @@ void VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatis #endif - Vector2 meanDirection2DItoK = Map3DTo2D (inv_transformK * meanDirectionI3D); - Vector2 meanDirection2DJtoK = Map3DTo2D (inv_transformK * meanDirectionJ3D); + Vector2 meanDirection2DItoK = Map3DTo2D(inv_transformK * meanDirectionI3D); + Vector2 meanDirection2DJtoK = Map3DTo2D(inv_transformK * meanDirectionJ3D); const float inv_weightK = (weightK > 0.f) ? embree::rcp(weightK) : 1.f; @@ -1022,12 +1037,17 @@ void VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatis const float sumWeightsJ = sumWeights[tmpJ.quot][tmpJ.rem]; const float sumWeightsK = sumWeightsI + sumWeightsJ; - //std::cout << "\tsumWeightsI: " << sumWeightsI << "\tsumWeightsJ: " << sumWeightsJ << "\tsumWeightsK: " << sumWeightsK << std::endl; - //std::cout << "\tnumSamplesI: " << numSamples[tmpI.quot][tmpI.rem] << "\tsumWeightsJ: " << numSamples[tmpJ.quot][tmpJ.rem] << std::endl; - + // std::cout << "\tsumWeightsI: " << sumWeightsI << "\tsumWeightsJ: " << sumWeightsJ << "\tsumWeightsK: " << sumWeightsK << std::endl; + // std::cout << "\tnumSamplesI: " << numSamples[tmpI.quot][tmpI.rem] << "\tsumWeightsJ: " << numSamples[tmpJ.quot][tmpJ.rem] << std::endl; - const Vector3 covarianceI = (sumWeightsI > 0.f) ? Vector3(splitWeightedSampleCovariances[tmpI.quot].x[tmpI.rem], splitWeightedSampleCovariances[tmpI.quot].y[tmpI.rem], splitWeightedSampleCovariances[tmpI.quot].z[tmpI.rem]) * embree::rcp(sumWeightsI) : Vector3(0.f); - const Vector3 covarianceJ = (sumWeightsJ > 0.f) ? Vector3(splitWeightedSampleCovariances[tmpJ.quot].x[tmpJ.rem], splitWeightedSampleCovariances[tmpJ.quot].y[tmpJ.rem], splitWeightedSampleCovariances[tmpJ.quot].z[tmpJ.rem]) * embree::rcp(sumWeightsJ) : Vector3(0.f); + const Vector3 covarianceI = (sumWeightsI > 0.f) ? Vector3(splitWeightedSampleCovariances[tmpI.quot].x[tmpI.rem], splitWeightedSampleCovariances[tmpI.quot].y[tmpI.rem], + splitWeightedSampleCovariances[tmpI.quot].z[tmpI.rem]) * + embree::rcp(sumWeightsI) + : Vector3(0.f); + const Vector3 covarianceJ = (sumWeightsJ > 0.f) ? Vector3(splitWeightedSampleCovariances[tmpJ.quot].x[tmpJ.rem], splitWeightedSampleCovariances[tmpJ.quot].y[tmpJ.rem], + splitWeightedSampleCovariances[tmpJ.quot].z[tmpJ.rem]) * + embree::rcp(sumWeightsJ) + : Vector3(0.f); #ifdef OPENPGL_ZERO_MEAN const Vector2 meanDirectionK2D(0.f); @@ -1039,7 +1059,7 @@ void VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatis Vector3 covarianceK = (weightI * covarianceI + weightI * meanII + weightJ * covarianceJ + weightJ * meanJJ); covarianceK *= inv_weightK; #ifndef OPENPGL_ZERO_MEAN - Vector3 meanKK = Vector3(meanDirectionK2D.x*meanDirectionK2D.x, meanDirectionK2D.y*meanDirectionK2D.y, meanDirectionK2D.x*meanDirectionK2D.y); + Vector3 meanKK = Vector3(meanDirectionK2D.x * meanDirectionK2D.x, meanDirectionK2D.y * meanDirectionK2D.y, meanDirectionK2D.x * meanDirectionK2D.y); covarianceK -= meanKK; #endif const Vector3 sampleCovarianceK = covarianceK * sumWeightsK; @@ -1094,8 +1114,9 @@ void VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatis numComponents--; } -template -std::vector::SplitCandidate > VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::getSplitCandidates() const +template +std::vector::SplitCandidate> +VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::getSplitCandidates() const { std::vector splitCandidates; for (size_t k = 0; k < numComponents; k++) @@ -1107,19 +1128,21 @@ std::vector::Spli splitCandidates.push_back(sc); } - std::sort(splitCandidates.begin(), splitCandidates.end(), [](SplitCandidate a, SplitCandidate b) {return a > b; }); + std::sort(splitCandidates.begin(), splitCandidates.end(), [](SplitCandidate a, SplitCandidate b) { + return a > b; + }); return splitCandidates; } -template +template void VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::clear(const size_t &_numComponents) { const embree::vfloat zeros(0.f); this->numComponents = _numComponents; - const int cnt = (this->numComponents + VMM::VectorSize-1) / VMM::VectorSize; + const int cnt = (this->numComponents + VMM::VectorSize - 1) / VMM::VectorSize; - for (size_t k =0; k < cnt; k++) + for (size_t k = 0; k < cnt; k++) { chiSquareMCEstimates[k] = zeros; splitWeightedSampleCovariances[k].x = zeros; @@ -1133,17 +1156,14 @@ void VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatis sumWeights[k] = zeros; sumAssignedSamples[k] = zeros; } - } - -template +template void VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::decay(const float &alpha) { + const int cnt = (this->numComponents + VMM::VectorSize - 1) / VMM::VectorSize; - const int cnt = (this->numComponents + VMM::VectorSize-1) / VMM::VectorSize; - - for (size_t k =0; k < cnt; k++) + for (size_t k = 0; k < cnt; k++) { splitWeightedSampleCovariances[k].x *= alpha; splitWeightedSampleCovariances[k].y *= alpha; @@ -1153,10 +1173,9 @@ void VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatis sumWeights[k] *= alpha; sumAssignedSamples[k] *= alpha; } - } -template +template size_t VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::getHighestChiSquareIdx() const { size_t maxIdx = 0; @@ -1173,25 +1192,25 @@ size_t VonMisesFisherChiSquareComponentSplitter::ComponentSplitStat return maxIdx; } -template +template void VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::clearAll() { this->clear(VMM::MaxComponents); } -template +template float VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::getChiSquareEst(const size_t &idx) const { const div_t tmp = div(idx, static_cast(VMM::VectorSize)); return chiSquareMCEstimates[tmp.quot][tmp.rem]; } -template +template float VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::getSumChiSquareEst() const { float sumChiSquareEst = 0.0f; - for ( int k = 0; k < numComponents; k++) + for (int k = 0; k < numComponents; k++) { const div_t tmp = div(k, static_cast(VMM::VectorSize)); sumChiSquareEst += chiSquareMCEstimates[tmp.quot][tmp.rem]; @@ -1199,24 +1218,27 @@ float VonMisesFisherChiSquareComponentSplitter::ComponentSplitStati return sumChiSquareEst; } -template +template std::string VonMisesFisherChiSquareComponentSplitter::ComponentSplitStatistics::toString() const { std::stringstream ss; ss << "ComponentSplitStatistics:" << std::endl; ss << "numComponents: " << numComponents << std::endl; float sumChiSquareEst = 0.0f; - //for ( int k = 0; k < numComponents; k++) - for ( int k = 0; k < VMM::MaxComponents; k++) + // for ( int k = 0; k < numComponents; k++) + for (int k = 0; k < VMM::MaxComponents; k++) { const div_t tmp = div(k, static_cast(VMM::VectorSize)); ss << "\t stats[" << k << "]: " << "chiSquareEst: " << chiSquareMCEstimates[tmp.quot][tmp.rem]; ss << std::endl; - ss << "\t" << "mean: [" << splitMeans[tmp.quot].x[tmp.rem] << ",\t" << splitMeans[tmp.quot].y[tmp.rem] << "]"; - ss << "\t samplevar: [" << splitWeightedSampleCovariances[tmp.quot].x[tmp.rem] << ",\t" << splitWeightedSampleCovariances[tmp.quot].y[tmp.rem]<< ",\t" << splitWeightedSampleCovariances[tmp.quot].z[tmp.rem] << "]"; - if(sumWeights[tmp.quot][tmp.rem] > 0.f) + ss << "\t" << "mean: [" << splitMeans[tmp.quot].x[tmp.rem] << ",\t" << splitMeans[tmp.quot].y[tmp.rem] << "]"; + ss << "\t samplevar: [" << splitWeightedSampleCovariances[tmp.quot].x[tmp.rem] << ",\t" << splitWeightedSampleCovariances[tmp.quot].y[tmp.rem] << ",\t" + << splitWeightedSampleCovariances[tmp.quot].z[tmp.rem] << "]"; + if (sumWeights[tmp.quot][tmp.rem] > 0.f) { - ss << "\t covar: [" << splitWeightedSampleCovariances[tmp.quot].x[tmp.rem] / sumWeights[tmp.quot][tmp.rem] << ",\t" << splitWeightedSampleCovariances[tmp.quot].y[tmp.rem] / sumWeights[tmp.quot][tmp.rem]<< ",\t" << splitWeightedSampleCovariances[tmp.quot].z[tmp.rem] / sumWeights[tmp.quot][tmp.rem] << "]"; + ss << "\t covar: [" << splitWeightedSampleCovariances[tmp.quot].x[tmp.rem] / sumWeights[tmp.quot][tmp.rem] << ",\t" + << splitWeightedSampleCovariances[tmp.quot].y[tmp.rem] / sumWeights[tmp.quot][tmp.rem] << ",\t" + << splitWeightedSampleCovariances[tmp.quot].z[tmp.rem] / sumWeights[tmp.quot][tmp.rem] << "]"; } else { @@ -1224,7 +1246,8 @@ std::string VonMisesFisherChiSquareComponentSplitter::ComponentSpli } ss << std::endl; - ss << "\t" << "numSamples: " << numSamples[tmp.quot][tmp.rem] << "\t sumWeights: " << sumWeights[tmp.quot][tmp.rem] << "\t sumAssignedSamples: " << sumAssignedSamples[tmp.quot][tmp.rem]; + ss << "\t" << "numSamples: " << numSamples[tmp.quot][tmp.rem] << "\t sumWeights: " << sumWeights[tmp.quot][tmp.rem] + << "\t sumAssignedSamples: " << sumAssignedSamples[tmp.quot][tmp.rem]; ss << std::endl; sumChiSquareEst += chiSquareMCEstimates[tmp.quot][tmp.rem]; @@ -1233,4 +1256,4 @@ std::string VonMisesFisherChiSquareComponentSplitter::ComponentSpli return ss.str(); } -} \ No newline at end of file +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/directional/vmm/VMMPhaseFunctions.cpp b/openpgl/directional/vmm/VMMPhaseFunctions.cpp index e78abb0..72a32ea 100644 --- a/openpgl/directional/vmm/VMMPhaseFunctions.cpp +++ b/openpgl/directional/vmm/VMMPhaseFunctions.cpp @@ -1,2456 +1,2456 @@ #include "VMMPhaseFunctions.h" -namespace openpgl { - - std::array VMMSingleLobeHenyeyGreensteinOracle::representations; - float VMMSingleLobeHenyeyGreensteinOracle::minMeanCosine; //{0.f}; - float VMMSingleLobeHenyeyGreensteinOracle::maxMeanCosine; //{0.99f}; - int VMMSingleLobeHenyeyGreensteinOracle::numRepresentations; - - - void VMMSingleLobeHenyeyGreensteinOracle::init() - { - /* VMM representations of the single lobe HG phase function. - The 3-lobe VMMs are fitted using a least squares optimization framework - as described by S. Herholz: - - "Path Guiding in Production" - - - "Volumetric Zero-variance Based Path Guiding" (Chapter 11.5) - */ - - minMeanCosine = 0.0f; - maxMeanCosine = 0.99f; - numRepresentations = 128; - - representations[0].K = 3; - representations[0].g = 0.0f; - representations[0].weights[0] = 0.01688512612073299f; - representations[0].meanCosines[0] = 0.0f; - representations[0].kappas[0] = 0.0f; - representations[0].normalizations[0] = 0.07957747154594767f; - representations[0].weights[1] = 0.34940739552081895f; - representations[0].meanCosines[1] = 0.0f; - representations[0].kappas[1] = 0.0f; - representations[0].normalizations[1] = 0.07957747154594767f; - representations[0].weights[2] = 0.6337074783584481f; - representations[0].meanCosines[2] = 0.0f; - representations[0].kappas[2] = 0.0f; - representations[0].normalizations[2] = 0.07957747154594767f; - representations[0].weights[3] = 0.0f; - representations[0].meanCosines[3] = 0.0f; - representations[0].kappas[3] = 0.0f; - representations[0].normalizations[3] = 0.0f; - - representations[1].K = 3; - representations[1].g = 0.007795275590551181f; - representations[1].weights[0] = 0.01688512612254555f; - representations[1].meanCosines[0] = 0.03588398182493312f; - representations[1].kappas[0] = 0.10774447737138962f; - representations[1].normalizations[0] = 0.08845920147738665f; - representations[1].weights[1] = 0.34940739552017397f; - representations[1].meanCosines[1] = 0.014362686373439479f; - representations[1].kappas[1] = 0.043093986007026464f; - representations[1].normalizations[1] = 0.08305603677895068f; - representations[1].weights[2] = 0.6337074783572806f; - representations[1].meanCosines[2] = 0.003425584458792068f; - representations[1].kappas[2] = 0.010276833773244303f; - representations[1].normalizations[2] = 0.08039807745351672f; - representations[1].weights[3] = 0.0f; - representations[1].meanCosines[3] = 0.0f; - representations[1].kappas[3] = 0.0f; - representations[1].normalizations[3] = 0.0f; - - representations[2].K = 3; - representations[2].g = 0.015590551181102362f; - representations[2].weights[0] = 0.01688437903886321f; - representations[2].meanCosines[0] = 0.07165186574299764f; - representations[2].kappas[0] = 0.21569511380458395f; - representations[2].normalizations[0] = 0.09797223006527885f; - representations[2].weights[1] = 0.34940741896923394f; - representations[2].meanCosines[1] = 0.028726867492049023f; - representations[2].kappas[1] = 0.08622805434824445f; - representations[2].normalizations[1] = 0.08663641125148722f; - representations[2].weights[2] = 0.6337082019919029f; - representations[2].meanCosines[2] = 0.006852355953716443f; - representations[2].kappas[2] = 0.02055771139312781f; - representations[2].normalizations[2] = 0.08122461225390147f; - representations[2].weights[3] = 0.0f; - representations[2].meanCosines[3] = 0.0f; - representations[2].kappas[3] = 0.0f; - representations[2].normalizations[3] = 0.0f; - - representations[3].K = 3; - representations[3].g = 0.02338582677165354f; - representations[3].weights[0] = 0.01688251644451822f; - representations[3].meanCosines[0] = 0.10719000956269134f; - representations[3].kappas[0] = 0.3240618203310573f; - representations[3].normalizations[0] = 0.10813182001250154f; - representations[3].weights[1] = 0.34940749421528944f; - representations[3].meanCosines[1] = 0.043094103168718915f; - representations[3].kappas[1] = 0.12944266757431747f; - representations[3].normalizations[1] = 0.09032214696897492f; - representations[3].weights[2] = 0.6337099893401924f; - representations[3].meanCosines[2] = 0.010281511556840308f; - representations[3].kappas[2] = 0.03084670860680498f; - representations[3].normalizations[2] = 0.0820574128582956f; - representations[3].weights[3] = 0.0f; - representations[3].meanCosines[3] = 0.0f; - representations[3].kappas[3] = 0.0f; - representations[3].normalizations[3] = 0.0f; - - representations[4].K = 3; - representations[4].g = 0.031181102362204723f; - representations[4].weights[0] = 0.016879170271827615f; - representations[4].meanCosines[0] = 0.14238854747740515f; - representations[4].kappas[0] = 0.43305883676258095f; - representations[4].normalizations[0] = 0.1189527446874129f; - representations[4].weights[1] = 0.3494076744789957f; - representations[4].meanCosines[1] = 0.05746593132255443f; - representations[4].kappas[1] = 0.17277859481192268f; - representations[4].normalizations[1] = 0.09411704443372311f; - representations[4].weights[2] = 0.6337131552491766f; - representations[4].meanCosines[2] = 0.013714266562698281f; - representations[4].kappas[2] = 0.04114795944743138f; - representations[4].normalizations[2] = 0.08289682936908468f; - representations[4].weights[3] = 0.0f; - representations[4].meanCosines[3] = 0.0f; - representations[4].kappas[3] = 0.0f; - representations[4].normalizations[3] = 0.0f; - - representations[5].K = 3; - representations[5].g = 0.0389763779527559f; - representations[5].weights[0] = 0.01688212081880487f; - representations[5].meanCosines[0] = 0.17712402739360683f; - representations[5].kappas[0] = 0.5428458438663006f; - representations[5].normalizations[0] = 0.13044306812363982f; - representations[5].weights[1] = 0.3494073468644722f; - representations[5].meanCosines[1] = 0.07184106550223494f; - representations[5].kappas[1] = 0.21626860707980294f; - representations[5].normalizations[1] = 0.09802439780640325f; - representations[5].weights[2] = 0.6337105323167227f; - representations[5].meanCosines[2] = 0.017151877226518623f; - representations[5].kappas[2] = 0.05146572636419975f; - representations[5].normalizations[2] = 0.08374323102430331f; - representations[5].weights[3] = 0.0f; - representations[5].meanCosines[3] = 0.0f; - representations[5].kappas[3] = 0.0f; - representations[5].normalizations[3] = 0.0f; - - representations[6].K = 3; - representations[6].g = 0.04677165354330708f; - representations[6].weights[0] = 0.016911780064021775f; - representations[6].meanCosines[0] = 0.2112319819771247f; - representations[6].kappas[0] = 0.6534261871553656f; - representations[6].normalizations[0] = 0.1425912900682853f; - representations[6].weights[1] = 0.349406832800622f; - representations[6].meanCosines[1] = 0.08621065078660167f; - representations[6].kappas[1] = 0.25992303076611534f; - representations[6].normalizations[1] = 0.10204555335170774f; - representations[6].weights[2] = 0.6336813871353562f; - representations[6].meanCosines[2] = 0.020595569081659132f; - representations[6].kappas[2] = 0.061804187012100144f; - representations[6].normalizations[2] = 0.08459698890239761f; - representations[6].weights[3] = 0.0f; - representations[6].meanCosines[3] = 0.0f; - representations[6].kappas[3] = 0.0f; - representations[6].normalizations[3] = 0.0f; - - representations[7].K = 3; - representations[7].g = 0.054566929133858265f; - representations[7].weights[0] = 0.01698431443686933f; - representations[7].meanCosines[0] = 0.24453864844476111f; - representations[7].kappas[0] = 0.764722497664732f; - representations[7].normalizations[0] = 0.1553715185073856f; - representations[7].weights[1] = 0.34940688968611067f; - representations[7].meanCosines[1] = 0.10056215754823958f; - representations[7].kappas[1] = 0.3037411707083553f; - representations[7].normalizations[1] = 0.10618074302045714f; - representations[7].weights[2] = 0.6336087958770199f; - representations[7].meanCosines[2] = 0.024046530657178572f; - representations[7].kappas[2] = 0.07216741718299197f; - representations[7].normalizations[2] = 0.08545847429102746f; - representations[7].weights[3] = 0.0f; - representations[7].meanCosines[3] = 0.0f; - representations[7].kappas[3] = 0.0f; - representations[7].normalizations[3] = 0.0f; - - representations[8].K = 3; - representations[8].g = 0.06236220472440945f; - representations[8].weights[0] = 0.017178062978008293f; - representations[8].meanCosines[0] = 0.2766513150830249f; - representations[8].kappas[0] = 0.8758112176782963f; - representations[8].normalizations[0] = 0.1686489715158632f; - representations[8].weights[1] = 0.34940624966149436f; - representations[8].meanCosines[1] = 0.11484549630313552f; - representations[8].kappas[1] = 0.34760648721076526f; - representations[8].normalizations[1] = 0.11041871452215614f; - representations[8].weights[2] = 0.6334156873604974f; - representations[8].meanCosines[2] = 0.027505759421599836f; - representations[8].kappas[2] = 0.08255892966571578f; - representations[8].normalizations[2] = 0.08632801972235461f; - representations[8].weights[3] = 0.0f; - representations[8].meanCosines[3] = 0.0f; - representations[8].kappas[3] = 0.0f; - representations[8].normalizations[3] = 0.0f; - - representations[9].K = 3; - representations[9].g = 0.07015748031496062f; - representations[9].weights[0] = 0.017371006808467492f; - representations[9].meanCosines[0] = 0.30782730487102705f; - representations[9].kappas[0] = 0.9879265175144101f; - representations[9].normalizations[0] = 0.18254148705094658f; - representations[9].weights[1] = 0.34928506189089986f; - representations[9].meanCosines[1] = 0.129131147364166f; - representations[9].kappas[1] = 0.3917729556957539f; - representations[9].normalizations[1] = 0.11478405680653793f; - representations[9].weights[2] = 0.6333439313006328f; - representations[9].meanCosines[2] = 0.030983196797823992f; - representations[9].kappas[2] = 0.09300913271687389f; - representations[9].normalizations[2] = 0.08720823784227144f; - representations[9].weights[3] = 0.0f; - representations[9].meanCosines[3] = 0.0f; - representations[9].kappas[3] = 0.0f; - representations[9].normalizations[3] = 0.0f; - - representations[10].K = 3; - representations[10].g = 0.0779527559055118f; - representations[10].weights[0] = 0.017584981738709496f; - representations[10].meanCosines[0] = 0.33794984524349103f; - representations[10].kappas[0] = 1.1009972551142273f; - representations[10].normalizations[0] = 0.1970156107265375f; - representations[10].weights[1] = 0.349155889550176f; - representations[10].meanCosines[1] = 0.1433912150580251f; - representations[10].kappas[1] = 0.4361939745876183f; - representations[10].normalizations[1] = 0.11927274711513454f; - representations[10].weights[2] = 0.6332591287111146f; - representations[10].meanCosines[2] = 0.034474217471298856f; - representations[10].kappas[2] = 0.10350469317865921f; - representations[10].normalizations[2] = 0.08809808759230493f; - representations[10].weights[3] = 0.0f; - representations[10].meanCosines[3] = 0.0f; - representations[10].kappas[3] = 0.0f; - representations[10].normalizations[3] = 0.0f; - - representations[11].K = 3; - representations[11].g = 0.08574803149606298f; - representations[11].weights[0] = 0.017809322999872215f; - representations[11].meanCosines[0] = 0.3670064050195432f; - representations[11].kappas[0] = 1.2152757532992868f; - representations[11].normalizations[0] = 0.21207747870839172f; - representations[11].weights[1] = 0.34897319658417403f; - representations[11].meanCosines[1] = 0.1576390635881601f; - representations[11].kappas[1] = 0.4809515295890107f; - representations[11].normalizations[1] = 0.12389359991430093f; - representations[11].weights[2] = 0.6332174804159536f; - representations[11].meanCosines[2] = 0.037984321862009805f; - representations[11].kappas[2] = 0.11406273217887339f; - representations[11].normalizations[2] = 0.08899910551739097f; - representations[11].weights[3] = 0.0f; - representations[11].meanCosines[3] = 0.0f; - representations[11].kappas[3] = 0.0f; - representations[11].normalizations[3] = 0.0f; - - representations[12].K = 3; - representations[12].g = 0.09354330708661417f; - representations[12].weights[0] = 0.01826527507863583f; - representations[12].meanCosines[0] = 0.3942271824887726f; - representations[12].kappas[0] = 1.3277678345776889f; - representations[12].normalizations[0] = 0.2272905167499025f; - representations[12].weights[1] = 0.3497662056173708f; - representations[12].meanCosines[1] = 0.17148377049971156f; - representations[12].kappas[1] = 0.5248424174065418f; - representations[12].normalizations[1] = 0.12851914003354303f; - representations[12].weights[2] = 0.6319685193039934f; - representations[12].meanCosines[2] = 0.04141831747731281f; - representations[12].kappas[2] = 0.12439730097148566f; - representations[12].normalizations[2] = 0.08988675023967237f; - representations[12].weights[3] = 0.0f; - representations[12].meanCosines[3] = 0.0f; - representations[12].kappas[3] = 0.0f; - representations[12].normalizations[3] = 0.0f; - - representations[13].K = 3; - representations[13].g = 0.10133858267716535f; - representations[13].weights[0] = 0.01876291998771093f; - representations[13].meanCosines[0] = 0.42020042532807644f; - representations[13].kappas[0] = 1.4408083884538716f; - representations[13].normalizations[0] = 0.24292636119361116f; - representations[13].weights[1] = 0.35061939871117465f; - representations[13].meanCosines[1] = 0.18520867376560435f; - representations[13].kappas[1] = 0.5687835020385287f; - representations[13].normalizations[1] = 0.13324175902122393f; - representations[13].weights[2] = 0.6306176813011145f; - representations[13].meanCosines[2] = 0.04484781190877385f; - representations[13].kappas[2] = 0.13472420647644337f; - representations[13].normalizations[2] = 0.09077936160410964f; - representations[13].weights[3] = 0.0f; - representations[13].meanCosines[3] = 0.0f; - representations[13].kappas[3] = 0.0f; - representations[13].normalizations[3] = 0.0f; - - representations[14].K = 3; - representations[14].g = 0.10913385826771653f; - representations[14].weights[0] = 0.019306961289135425f; - representations[14].meanCosines[0] = 0.44492057851788697f; - representations[14].kappas[0] = 1.5543850149507152f; - representations[14].normalizations[0] = 0.25895176916401214f; - representations[14].weights[1] = 0.35154945670839527f; - representations[14].meanCosines[1] = 0.19879827489247553f; - representations[14].kappas[1] = 0.6127546945467943f; - representations[14].normalizations[1] = 0.1380578383493104f; - representations[14].weights[2] = 0.6291435820024692f; - representations[14].meanCosines[2] = 0.0482705272418375f; - representations[14].kappas[2] = 0.14503705196651462f; - representations[14].normalizations[2] = 0.0916763629745512f; - representations[14].weights[3] = 0.0f; - representations[14].meanCosines[3] = 0.0f; - representations[14].kappas[3] = 0.0f; - representations[14].normalizations[3] = 0.0f; - - representations[15].K = 3; - representations[15].g = 0.11692913385826771f; - representations[15].weights[0] = 0.01989845510400388f; - representations[15].meanCosines[0] = 0.4684068719141528f; - representations[15].kappas[0] = 1.6685346475413192f; - representations[15].normalizations[0] = 0.2753414373527367f; - representations[15].weights[1] = 0.35255534710456443f; - representations[15].meanCosines[1] = 0.21224370805221723f; - representations[15].kappas[1] = 0.6567552077580507f; - representations[15].normalizations[1] = 0.1429656644773955f; - representations[15].weights[2] = 0.6275461977914317f; - representations[15].meanCosines[2] = 0.051685704986140286f; - representations[15].kappas[2] = 0.155334002273931f; - representations[15].normalizations[2] = 0.09257756389054712f; - representations[15].weights[3] = 0.0f; - representations[15].meanCosines[3] = 0.0f; - representations[15].kappas[3] = 0.0f; - representations[15].normalizations[3] = 0.0f; - - representations[16].K = 3; - representations[16].g = 0.1247244094488189f; - representations[16].weights[0] = 0.020535354184989436f; - representations[16].meanCosines[0] = 0.49069955616971095f; - representations[16].kappas[0] = 1.7833511441174834f; - representations[16].normalizations[0] = 0.292080078167316f; - representations[16].weights[1] = 0.353622508898923f; - representations[16].meanCosines[1] = 0.22554330566749264f; - representations[16].kappas[1] = 0.7008064498892924f; - representations[16].normalizations[1] = 0.14796596420736946f; - representations[16].weights[2] = 0.6258421369160876f; - representations[16].meanCosines[2] = 0.055094314525624195f; - representations[16].kappas[2] = 0.16561842664237564f; - representations[16].normalizations[2] = 0.09348322926408528f; - representations[16].weights[3] = 0.0f; - representations[16].meanCosines[3] = 0.0f; - representations[16].kappas[3] = 0.0f; - representations[16].normalizations[3] = 0.0f; - - representations[17].K = 3; - representations[17].g = 0.13251968503937006f; - representations[17].weights[0] = 0.021218949410057832f; - representations[17].meanCosines[0] = 0.5118356933074103f; - representations[17].kappas[0] = 1.8988787667383773f; - representations[17].normalizations[0] = 0.30914733250021437f; - representations[17].weights[1] = 0.3547509744956134f; - representations[17].meanCosines[1] = 0.23868968600098744f; - representations[17].kappas[1] = 0.7449098193050739f; - representations[17].normalizations[1] = 0.15305721242482156f; - representations[17].weights[2] = 0.6240300760943289f; - representations[17].meanCosines[2] = 0.05849576027428436f; - representations[17].kappas[2] = 0.1758889715094559f; - representations[17].normalizations[2] = 0.09439321119322305f; - representations[17].weights[3] = 0.0f; - representations[17].meanCosines[3] = 0.0f; - representations[17].kappas[3] = 0.0f; - representations[17].normalizations[3] = 0.0f; - - representations[18].K = 3; - representations[18].g = 0.14031496062992124f; - representations[18].weights[0] = 0.021949824475763605f; - representations[18].meanCosines[0] = 0.5318607735970473f; - representations[18].kappas[0] = 2.0151765919095097f; - representations[18].normalizations[0] = 0.32652706617217647f; - representations[18].weights[1] = 0.355937499042096f; - representations[18].meanCosines[1] = 0.2516775828350221f; - representations[18].kappas[1] = 0.7890721855355327f; - representations[18].normalizations[1] = 0.15823845763667177f; - representations[18].weights[2] = 0.6221126764821404f; - representations[18].meanCosines[2] = 0.06188987023100114f; - representations[18].kappas[2] = 0.1861455542022604f; - representations[18].normalizations[2] = 0.095307472119436f; - representations[18].weights[3] = 0.0f; - representations[18].meanCosines[3] = 0.0f; - representations[18].kappas[3] = 0.0f; - representations[18].normalizations[3] = 0.0f; - - representations[19].K = 3; - representations[19].g = 0.14811023622047242f; - representations[19].weights[0] = 0.02272913643627242f; - representations[19].meanCosines[0] = 0.5508226752301884f; - representations[19].kappas[0] = 2.1322958845677973f; - representations[19].normalizations[0] = 0.34420411555954816f; - representations[19].weights[1] = 0.35718094247354754f; - representations[19].meanCosines[1] = 0.2645011566729811f; - representations[19].kappas[1] = 0.83329691124312f; - representations[19].normalizations[1] = 0.16350830114410747f; - representations[19].weights[2] = 0.6200899210901799f; - representations[19].meanCosines[2] = 0.06527619808965157f; - representations[19].kappas[2] = 0.19638725613213096f; - representations[19].normalizations[2] = 0.09622589876681735f; - representations[19].weights[3] = 0.0f; - representations[19].meanCosines[3] = 0.0f; - representations[19].kappas[3] = 0.0f; - representations[19].normalizations[3] = 0.0f; - - representations[20].K = 3; - representations[20].g = 0.1559055118110236f; - representations[20].weights[0] = 0.02355816434063645f; - representations[20].meanCosines[0] = 0.5687717007838606f; - representations[20].kappas[0] = 2.2502875905814577f; - representations[20].normalizations[0] = 0.3621653738462567f; - representations[20].weights[1] = 0.35848028814660143f; - representations[20].meanCosines[1] = 0.27715490333500015f; - representations[20].kappas[1] = 0.877586789540549f; - representations[20].normalizations[1] = 0.1688652288634378f; - representations[20].weights[2] = 0.6179615475127621f; - representations[20].meanCosines[2] = 0.06865425253449127f; - representations[20].kappas[2] = 0.20661301330820872f; - representations[20].normalizations[2] = 0.09714836239583771f; - representations[20].weights[3] = 0.0f; - representations[20].meanCosines[3] = 0.0f; - representations[20].kappas[3] = 0.0f; - representations[20].normalizations[3] = 0.0f; - - representations[21].K = 3; - representations[21].g = 0.1637007874015748f; - representations[21].weights[0] = 0.024437905025832977f; - representations[21].meanCosines[0] = 0.5857605240246847f; - representations[21].kappas[0] = 2.369210817881718f; - representations[21].normalizations[0] = 0.3804010540382946f; - representations[21].weights[1] = 0.3598331385814581f; - representations[21].meanCosines[1] = 0.2896345928505576f; - representations[21].kappas[1] = 0.9219473564693016f; - representations[21].normalizations[1] = 0.17430802225670775f; - representations[21].weights[2] = 0.615728956392709f; - representations[21].meanCosines[2] = 0.0720237515533397f; - representations[21].kappas[2] = 0.21682238610695004f; - representations[21].normalizations[2] = 0.0980747884961609f; - representations[21].weights[3] = 0.0f; - representations[21].meanCosines[3] = 0.0f; - representations[21].kappas[3] = 0.0f; - representations[21].normalizations[3] = 0.0f; - - representations[22].K = 3; - representations[22].g = 0.17149606299212597f; - representations[22].weights[0] = 0.02536961631311807f; - representations[22].meanCosines[0] = 0.6018414369673392f; - representations[22].kappas[0] = 2.4891221301227326f; - representations[22].normalizations[0] = 0.3989029937166436f; - representations[22].weights[1] = 0.36123782439484414f; - representations[22].meanCosines[1] = 0.3019360372422726f; - representations[22].kappas[1] = 0.9663826317493759f; - representations[22].normalizations[1] = 0.1798352546930349f; - representations[22].weights[2] = 0.6133925592920377f; - representations[22].meanCosines[2] = 0.07538429370718021f; - representations[22].kappas[2] = 0.227014564370858f; - representations[22].normalizations[2] = 0.09900506739744325f; - representations[22].weights[3] = 0.0f; - representations[22].meanCosines[3] = 0.0f; - representations[22].kappas[3] = 0.0f; - representations[22].normalizations[3] = 0.0f; - - representations[23].K = 3; - representations[23].g = 0.17929133858267715f; - representations[23].weights[0] = 0.026354489815300336f; - representations[23].meanCosines[0] = 0.6170665107763216f; - representations[23].kappas[0] = 2.6100823069456927f; - representations[23].normalizations[0] = 0.41766558456512115f; - representations[23].weights[1] = 0.3626921762477047f; - representations[23].meanCosines[1] = 0.3140558294414811f; - representations[23].kappas[1] = 1.01089774821742f; - representations[23].normalizations[1] = 0.18544561804238008f; - representations[23].weights[2] = 0.6109533339369949f; - representations[23].meanCosines[2] = 0.07873555976785689f; - representations[23].kappas[2] = 0.23718897773507175f; - representations[23].normalizations[2] = 0.09993910949879477f; - representations[23].weights[3] = 0.0f; - representations[23].meanCosines[3] = 0.0f; - representations[23].kappas[3] = 0.0f; - representations[23].normalizations[3] = 0.0f; - - representations[24].K = 3; - representations[24].g = 0.18708661417322833f; - representations[24].weights[0] = 0.027393813480758946f; - representations[24].meanCosines[0] = 0.6314864653894078f; - representations[24].kappas[0] = 2.732153035175755f; - representations[24].normalizations[0] = 0.43668514425861027f; - representations[24].weights[1] = 0.36419412912481675f; - representations[24].meanCosines[1] = 0.3259909557058004f; - representations[24].kappas[1] = 1.0554976150974884f; - representations[24].normalizations[1] = 0.19113776574149305f; - representations[24].weights[2] = 0.6084120573944244f; - representations[24].meanCosines[2] = 0.0820772098121622f; - representations[24].kappas[2] = 0.24734498362097554f; - representations[24].normalizations[2] = 0.10087681703497244f; - representations[24].weights[3] = 0.0f; - representations[24].meanCosines[3] = 0.0f; - representations[24].kappas[3] = 0.0f; - representations[24].normalizations[3] = 0.0f; - - representations[25].K = 3; - representations[25].g = 0.19488188976377951f; - representations[25].weights[0] = 0.02848894330183947f; - representations[25].meanCosines[0] = 0.6451502887946322f; - representations[25].kappas[0] = 2.855397531861139f; - representations[25].normalizations[0] = 0.4559598770309509f; - representations[25].weights[1] = 0.3657416121853952f; - representations[25].meanCosines[1] = 0.3377388443459699f; - representations[25].kappas[1] = 1.1001871225871562f; - representations[25].normalizations[1] = 0.19691034293610063f; - representations[25].weights[2] = 0.6057694445127654f; - representations[25].meanCosines[2] = 0.08540889854051824f; - representations[25].kappas[2] = 0.2574819131914485f; - representations[25].normalizations[2] = 0.10181808818723857f; - representations[25].weights[3] = 0.0f; - representations[25].meanCosines[3] = 0.0f; - representations[25].kappas[3] = 0.0f; - representations[25].normalizations[3] = 0.0f; - - representations[26].K = 3; - representations[26].g = 0.2026771653543307f; - representations[26].weights[0] = 0.029641232684561578f; - representations[26].meanCosines[0] = 0.6581050795977398f; - representations[26].kappas[0] = 2.979882270484645f; - representations[26].normalizations[0] = 0.47549000441135625f; - representations[26].weights[1] = 0.36733232742198196f; - representations[26].meanCosines[1] = 0.34929751692855454f; - representations[26].kappas[1] = 1.1449717768941352f; - representations[26].normalizations[1] = 0.20276207496603466f; - representations[26].weights[2] = 0.6030264398934564f; - representations[26].meanCosines[2] = 0.0887303226670217f; - representations[26].kappas[2] = 0.267599215342648f; - representations[26].normalizations[2] = 0.10276283052115276f; - representations[26].weights[3] = 0.0f; - representations[26].meanCosines[3] = 0.0f; - representations[26].kappas[3] = 0.0f; - representations[26].normalizations[3] = 0.0f; - - representations[27].K = 3; - representations[27].g = 0.21047244094488188f; - representations[27].weights[0] = 0.03085210788273518f; - representations[27].meanCosines[0] = 0.6703956245596104f; - representations[27].kappas[0] = 3.1056753595617264f; - representations[27].normalizations[0] = 0.4952773717297844f; - representations[27].weights[1] = 0.3689640002885473f; - representations[27].meanCosines[1] = 0.3606653920204467f; - representations[27].kappas[1] = 1.1898570305342318f; - representations[27].normalizations[1] = 0.20869168777485336f; - representations[27].weights[2] = 0.6001838918287176f; - representations[27].meanCosines[2] = 0.09204116986781731f; - representations[27].kappas[2] = 0.27769630133596485f; - representations[27].normalizations[2] = 0.10371094668741296f; - representations[27].weights[3] = 0.0f; - representations[27].meanCosines[3] = 0.0f; - representations[27].kappas[3] = 0.0f; - representations[27].normalizations[3] = 0.0f; - - representations[28].K = 3; - representations[28].g = 0.21826771653543306f; - representations[28].weights[0] = 0.03212300887954878f; - representations[28].meanCosines[0] = 0.6820644132559194f; - representations[28].kappas[0] = 3.2328480493359963f; - representations[28].normalizations[0] = 0.5153255463626063f; - representations[28].weights[1] = 0.3706342080413193f; - representations[28].meanCosines[1] = 0.371841402019988f; - representations[28].kappas[1] = 1.2348488131529798f; - representations[28].normalizations[1] = 0.21469798321963257f; - representations[28].weights[2] = 0.597242783079132f; - representations[28].meanCosines[2] = 0.095341157518617f; - representations[28].kappas[2] = 0.28777266268317936f; - representations[28].normalizations[2] = 0.10466234550768412f; - representations[28].weights[3] = 0.0f; - representations[28].meanCosines[3] = 0.0f; - representations[28].kappas[3] = 0.0f; - representations[28].normalizations[3] = 0.0f; - - representations[29].K = 3; - representations[29].g = 0.22606299212598424f; - representations[29].weights[0] = 0.03345544514793685f; - representations[29].meanCosines[0] = 0.6931514474568911f; - representations[29].kappas[0] = 3.3614734966515782f; - representations[29].normalizations[0] = 0.5356394908307532f; - representations[29].weights[1] = 0.37234054521898624f; - representations[29].meanCosines[1] = 0.3828248418078445f; - representations[29].kappas[1] = 1.2799530194570734f; - representations[29].normalizations[1] = 0.22077977707335444f; - representations[29].weights[2] = 0.5942040096330768f; - representations[29].meanCosines[2] = 0.09862999422597651f; - representations[29].kappas[2] = 0.29782775373429926f; - representations[29].normalizations[2] = 0.10561693102809376f; - representations[29].weights[3] = 0.0f; - representations[29].meanCosines[3] = 0.0f; - representations[29].kappas[3] = 0.0f; - representations[29].normalizations[3] = 0.0f; - - representations[30].K = 3; - representations[30].g = 0.23385826771653542f; - representations[30].weights[0] = 0.0348509218277539f; - representations[30].meanCosines[0] = 0.703694400485129f; - representations[30].kappas[0] = 3.491628707455712f; - representations[30].normalizations[0] = 0.5562257439894829f; - representations[30].weights[1] = 0.3740804275025195f; - representations[30].meanCosines[1] = 0.39361551569233905f; - representations[30].kappas[1] = 1.325176201006904f; - representations[30].normalizations[1] = 0.22693599717230062f; - representations[30].weights[2] = 0.5910686506697266f; - representations[30].meanCosines[2] = 0.10190742993352812f; - representations[30].kappas[2] = 0.3078611447237137f; - representations[30].normalizations[2] = 0.10657461709345743f; - representations[30].weights[3] = 0.0f; - representations[30].meanCosines[3] = 0.0f; - representations[30].kappas[3] = 0.0f; - representations[30].normalizations[3] = 0.0f; - - representations[31].K = 3; - representations[31].g = 0.2416535433070866f; - representations[31].weights[0] = 0.0363110174513472f; - representations[31].meanCosines[0] = 0.7137284878918613f; - representations[31].kappas[0] = 3.6233927446497733f; - representations[31].normalizations[0] = 0.5770920215898871f; - representations[31].weights[1] = 0.3758513101926688f; - representations[31].meanCosines[1] = 0.40421353232046997f; - representations[31].kappas[1] = 1.370524826949544f; - representations[31].normalizations[1] = 0.23316558894026745f; - representations[31].weights[2] = 0.5878376723559839f; - representations[31].meanCosines[2] = 0.10517320052735003f; - representations[31].kappas[2] = 0.3178723524295186f; - representations[31].normalizations[2] = 0.10753531137309834f; - representations[31].weights[3] = 0.0f; - representations[31].meanCosines[3] = 0.0f; - representations[31].kappas[3] = 0.0f; - representations[31].normalizations[3] = 0.0f; - - representations[32].K = 3; - representations[32].g = 0.2494488188976378f; - representations[32].weights[0] = 0.03783733033391697f; - representations[32].meanCosines[0] = 0.7232866503493903f; - representations[32].kappas[0] = 3.7568481915190235f; - representations[32].normalizations[0] = 0.5982473403971204f; - representations[32].weights[1] = 0.377650546588742f; - representations[32].meanCosines[1] = 0.4146194044606831f; - representations[32].kappas[1] = 1.416005797772609f; - representations[32].normalizations[1] = 0.23946758934791837f; - representations[32].weights[2] = 0.5845121230773409f; - representations[32].meanCosines[2] = 0.10842706502773718f; - representations[32].kappas[2] = 0.32786095389288733f; - representations[32].normalizations[2] = 0.10849892624542931f; - representations[32].weights[3] = 0.0f; - representations[32].meanCosines[3] = 0.0f; - representations[32].kappas[3] = 0.0f; - representations[32].normalizations[3] = 0.0f; - - representations[33].K = 3; - representations[33].g = 0.25724409448818897f; - representations[33].weights[0] = 0.039431478172527346f; - representations[33].meanCosines[0] = 0.7323996378740554f; - representations[33].kappas[0] = 3.892081342390479f; - representations[33].normalizations[0] = 0.6197019514445599f; - representations[33].weights[1] = 0.37947540366321675f; - representations[33].meanCosines[1] = 0.42483402082021005f; - representations[33].kappas[1] = 1.4616264505862715f; - representations[33].normalizations[1] = 0.2458411328184177f; - representations[33].weights[2] = 0.5810931181642559f; - representations[33].meanCosines[2] = 0.11166880441579947f; - representations[33].kappas[2] = 0.33782658307981484f; - representations[33].normalizations[2] = 0.10946537864825562f; - representations[33].weights[3] = 0.0f; - representations[33].meanCosines[3] = 0.0f; - representations[33].kappas[3] = 0.0f; - representations[33].normalizations[3] = 0.0f; - - representations[34].K = 3; - representations[34].g = 0.2650393700787401f; - representations[34].weights[0] = 0.04109511413829938f; - representations[34].meanCosines[0] = 0.7410960812812006f; - representations[34].kappas[0] = 4.029181949359587f; - representations[34].normalizations[0] = 0.6414672123825825f; - representations[34].weights[1] = 0.3813231066295435f; - representations[34].meanCosines[1] = 0.43485858368855124f; - representations[34].kappas[1] = 1.5073944073067256f; - representations[34].normalizations[1] = 0.2522854344127896f; - representations[34].weights[2] = 0.5775817792321571f; - representations[34].meanCosines[2] = 0.1148982096999848f; - representations[34].kappas[2] = 0.3477688944033129f; - representations[34].normalizations[2] = 0.11043458667809568f; - representations[34].weights[3] = 0.0f; - representations[34].meanCosines[3] = 0.0f; - representations[34].kappas[3] = 0.0f; - representations[34].normalizations[3] = 0.0f; - - representations[35].K = 3; - representations[35].g = 0.27283464566929133f; - representations[35].weights[0] = 0.04282992980429418f; - representations[35].meanCosines[0] = 0.7494026016728395f; - representations[35].kappas[0] = 4.1682433077297265f; - representations[35].normalizations[0] = 0.6635555227768634f; - representations[35].weights[1] = 0.3831908473467149f; - representations[35].meanCosines[1] = 0.4446945773353679f; - representations[35].kappas[1] = 1.5533175460677648f; - representations[35].normalizations[1] = 0.258799789085319f; - representations[35].weights[2] = 0.5739792228489909f; - representations[35].meanCosines[2] = 0.11811507896449913f; - representations[35].kappas[2] = 0.35768755366547783f; - representations[35].normalizations[2] = 0.11140646877150544f; - representations[35].weights[3] = 0.0f; - representations[35].meanCosines[3] = 0.0f; - representations[35].kappas[3] = 0.0f; - representations[35].normalizations[3] = 0.0f; - - representations[36].K = 3; - representations[36].g = 0.2806299212598425f; - representations[36].weights[0] = 0.04463760356304057f; - representations[36].meanCosines[0] = 0.7573440065673147f; - representations[36].kappas[0] = 4.309363834506902f; - representations[36].normalizations[0] = 0.685980505664905f; - representations[36].weights[1] = 0.3850756892916237f; - representations[36].meanCosines[1] = 0.4543438495874592f; - representations[36].kappas[1] = 1.5994045135644068f; - representations[36].normalizations[1] = 0.2653836478950735f; - representations[36].weights[2] = 0.5702867071453358f; - representations[36].meanCosines[2] = 0.12131925204563446f; - representations[36].kappas[2] = 0.3675823452228001f; - representations[36].normalizations[2] = 0.1123809543338033f; - representations[36].weights[3] = 0.0f; - representations[36].meanCosines[3] = 0.0f; - representations[36].kappas[3] = 0.0f; - representations[36].normalizations[3] = 0.0f; - - representations[37].K = 3; - representations[37].g = 0.2884251968503937f; - representations[37].weights[0] = 0.04651992132996143f; - representations[37].meanCosines[0] = 0.7649432204882097f; - representations[37].kappas[0] = 4.452644004080665f; - representations[37].normalizations[0] = 0.7087564597863664f; - representations[37].weights[1] = 0.3869748043395022f; - representations[37].meanCosines[1] = 0.46380833521269565f; - representations[37].kappas[1] = 1.6456635357182618f; - representations[37].normalizations[1] = 0.2720364511995345f; - representations[37].weights[2] = 0.5665052743305363f; - representations[37].meanCosines[2] = 0.12451052633673292f; - representations[37].kappas[2] = 0.3774529122318213f; - representations[37].normalizations[2] = 0.11335795827691708f; - representations[37].weights[3] = 0.0f; - representations[37].meanCosines[3] = 0.0f; - representations[37].kappas[3] = 0.0f; - representations[37].normalizations[3] = 0.0f; - - representations[38].K = 3; - representations[38].g = 0.29622047244094485f; - representations[38].weights[0] = 0.04847852891549287f; - representations[38].meanCosines[0] = 0.7722217618748662f; - representations[38].kappas[0] = 4.5981933220302285f; - representations[38].normalizations[0] = 0.7318994148658073f; - representations[38].weights[1] = 0.388885024846989f; - representations[38].meanCosines[1] = 0.473090536062836f; - representations[38].kappas[1] = 1.6921048843771227f; - representations[38].normalizations[1] = 0.27875798554095554f; - representations[38].weights[2] = 0.5626364462375181f; - representations[38].meanCosines[2] = 0.12768882647952162f; - representations[38].kappas[2] = 0.38729928159477f; - representations[38].normalizations[2] = 0.11433743303630248f; - representations[38].weights[3] = 0.0f; - representations[38].meanCosines[3] = 0.0f; - representations[38].kappas[3] = 0.0f; - representations[38].normalizations[3] = 0.0f; - - representations[39].K = 3; - representations[39].g = 0.30401574803149606f; - representations[39].weights[0] = 0.050515288560540404f; - representations[39].meanCosines[0] = 0.7791993428816343f; - representations[39].kappas[0] = 4.746120804250555f; - representations[39].normalizations[0] = 0.7554255718985057f; - representations[39].weights[1] = 0.39080348821235833f; - representations[39].meanCosines[1] = 0.4821927734544212f; - representations[39].kappas[1] = 1.7387373336802003f; - representations[39].normalizations[1] = 0.28554787556787525f; - representations[39].weights[2] = 0.5586812232271012f; - representations[39].meanCosines[2] = 0.13085395797040394f; - representations[39].kappas[2] = 0.39712110186372734f; - representations[39].normalizations[2] = 0.11531929316013426f; - representations[39].weights[3] = 0.0f; - representations[39].meanCosines[3] = 0.0f; - representations[39].kappas[3] = 0.0f; - representations[39].normalizations[3] = 0.0f; - - representations[40].K = 3; - representations[40].g = 0.3118110236220472f; - representations[40].weights[0] = 0.052631938361106065f; - representations[40].meanCosines[0] = 0.785894454230334f; - representations[40].kappas[0] = 4.896544587693031f; - representations[40].normalizations[0] = 0.7793527912550628f; - representations[40].weights[1] = 0.3927270435107326f; - representations[40].meanCosines[1] = 0.4911178490442006f; - representations[40].kappas[1] = 1.7855715658402957f; - representations[40].normalizations[1] = 0.2924060777270106f; - representations[40].weights[2] = 0.5546410181281614f; - representations[40].meanCosines[2] = 0.13400584044657948f; - representations[40].kappas[2] = 0.406918365828317f; - representations[40].normalizations[2] = 0.1163034871611057f; - representations[40].weights[3] = 0.0f; - representations[40].meanCosines[3] = 0.0f; - representations[40].kappas[3] = 0.0f; - representations[40].normalizations[3] = 0.0f; - - representations[41].K = 3; - representations[41].g = 0.3196062992125984f; - representations[41].weights[0] = 0.054830320932235194f; - representations[41].meanCosines[0] = 0.7923241563653624f; - representations[41].kappas[0] = 5.049585889496475f; - representations[41].normalizations[0] = 0.8036995978580225f; - representations[41].weights[1] = 0.39465264154304214f; - representations[41].meanCosines[1] = 0.49986856925941164f; - representations[41].kappas[1] = 1.8326178990052264f; - representations[41].normalizations[1] = 0.299332552386369f; - representations[41].weights[2] = 0.5505170375247227f; - representations[41].meanCosines[2] = 0.13714435057395352f; - representations[41].kappas[2] = 0.4166909238221657f; - representations[41].normalizations[2] = 0.11728994912473324f; - representations[41].weights[3] = 0.0f; - representations[41].meanCosines[3] = 0.0f; - representations[41].kappas[3] = 0.0f; - representations[41].normalizations[3] = 0.0f; - - representations[42].K = 3; - representations[42].g = 0.3274015748031496f; - representations[42].weights[0] = 0.05711223605872792f; - representations[42].meanCosines[0] = 0.7985043630899611f; - representations[42].kappas[0] = 5.205373425292967f; - representations[42].normalizations[0] = 0.828485854647965f; - representations[42].weights[1] = 0.39657710712907207f; - representations[42].meanCosines[1] = 0.5084480072544973f; - representations[42].kappas[1] = 1.8798877748028617f; - representations[42].normalizations[1] = 0.30632748244974595f; - representations[42].weights[2] = 0.5463106568122f; - representations[42].meanCosines[2] = 0.14026942121314215f; - representations[42].kappas[2] = 0.4264387921091299f; - representations[42].normalizations[2] = 0.11827862972883287f; - representations[42].weights[3] = 0.0f; - representations[42].meanCosines[3] = 0.0f; - representations[42].kappas[3] = 0.0f; - representations[42].normalizations[3] = 0.0f; - - representations[43].K = 3; - representations[43].g = 0.3351968503937008f; - representations[43].weights[0] = 0.05947949976675226f; - representations[43].meanCosines[0] = 0.8044498524567503f; - representations[43].kappas[0] = 5.3640421044192195f; - representations[43].normalizations[0] = 0.8537325301915992f; - representations[43].weights[1] = 0.39849724129514225f; - representations[43].meanCosines[1] = 0.516859365291507f; - representations[43].kappas[1] = 1.9273931827012034f; - representations[43].normalizations[1] = 0.31339119081328726f; - representations[43].weights[2] = 0.5420232589381055f; - representations[43].meanCosines[2] = 0.14338100028624415f; - representations[43].kappas[2] = 0.4361620257500823f; - representations[43].normalizations[2] = 0.11926948366904784f; - representations[43].weights[3] = 0.0f; - representations[43].meanCosines[3] = 0.0f; - representations[43].kappas[3] = 0.0f; - representations[43].normalizations[3] = 0.0f; - - representations[44].K = 3; - representations[44].g = 0.34299212598425194f; - representations[44].weights[0] = 0.061934017335778434f; - representations[44].meanCosines[0] = 0.8101742785481437f; - representations[44].kappas[0] = 5.525731270151455f; - representations[44].normalizations[0] = 0.8794613975566535f; - representations[44].weights[1] = 0.400409908304721f; - representations[44].meanCosines[1] = 0.5251058303099392f; - representations[44].kappas[1] = 1.9751459448430044f; - representations[44].normalizations[1] = 0.32052403397373247f; - representations[44].weights[2] = 0.5376560743595005f; - representations[44].meanCosines[2] = 0.14647900283272577f; - representations[44].kappas[2] = 0.4458605687980155f; - representations[44].normalizations[2] = 0.12026245438736198f; - representations[44].weights[3] = 0.0f; - representations[44].meanCosines[3] = 0.0f; - representations[44].kappas[3] = 0.0f; - representations[44].normalizations[3] = 0.0f; - - representations[45].K = 3; - representations[45].g = 0.35078740157480315f; - representations[45].weights[0] = 0.06447760472630311f; - representations[45].meanCosines[0] = 0.8156904376058959f; - representations[45].kappas[0] = 5.6905902250879805f; - representations[45].normalizations[0] = 0.9056958957694585f; - representations[45].weights[1] = 0.40231181608214067f; - representations[45].meanCosines[1] = 0.533190870036375f; - representations[45].kappas[1] = 2.0231595316319937f; - representations[45].normalizations[1] = 0.3277266730567593f; - representations[45].weights[2] = 0.5332105791915562f; - representations[45].meanCosines[2] = 0.14956342791040378f; - representations[45].kappas[2] = 0.4555346203324962f; - representations[45].normalizations[2] = 0.1212575115536747f; - representations[45].weights[3] = 0.0f; - representations[45].meanCosines[3] = 0.0f; - representations[45].kappas[3] = 0.0f; - representations[45].normalizations[3] = 0.0f; - - representations[46].K = 3; - representations[46].g = 0.3585826771653543f; - representations[46].weights[0] = 0.06711202650241141f; - representations[46].meanCosines[0] = 0.8210102816127492f; - representations[46].kappas[0] = 5.858777649296523f; - representations[46].normalizations[0] = 0.9324610224429561f; - representations[46].weights[1] = 0.4041995962417163f; - representations[46].meanCosines[1] = 0.5411181321395668f; - representations[46].kappas[1] = 2.071448705643941f; - representations[46].normalizations[1] = 0.335000023620412f; - representations[46].weights[2] = 0.5286883772558724f; - representations[46].meanCosines[2] = 0.15263433078191485f; - representations[46].kappas[2] = 0.4651845494691381f; - representations[46].normalizations[2] = 0.12225464287484415f; - representations[46].weights[3] = 0.0f; - representations[46].meanCosines[3] = 0.0f; - representations[46].kappas[3] = 0.0f; - representations[46].normalizations[3] = 0.0f; - - representations[47].K = 3; - representations[47].g = 0.3663779527559055f; - representations[47].weights[0] = 0.06983934101319342f; - representations[47].meanCosines[0] = 0.8261446758646345f; - representations[47].kappas[0] = 6.030451916295631f; - representations[47].normalizations[0] = 0.9597817802216335f; - representations[47].weights[1] = 0.40607015469631597f; - representations[47].meanCosines[1] = 0.5488908666357898f; - representations[47].kappas[1] = 2.120026074834621f; - representations[47].normalizations[1] = 0.3423447352950037f; - representations[47].weights[2] = 0.5240905042904906f; - representations[47].meanCosines[2] = 0.1556916023453696f; - representations[47].kappas[2] = 0.47481020201532553f; - representations[47].normalizations[2] = 0.12325378236504182f; - representations[47].weights[3] = 0.0f; - representations[47].meanCosines[3] = 0.0f; - representations[47].kappas[3] = 0.0f; - representations[47].normalizations[3] = 0.0f; - - representations[48].K = 3; - representations[48].g = 0.37417322834645667f; - representations[48].weights[0] = 0.07266134359728532f; - representations[48].meanCosines[0] = 0.8311039776930013f; - representations[48].kappas[0] = 6.20578789794099f; - representations[48].normalizations[0] = 0.9876858407915654f; - representations[48].weights[1] = 0.40792008616982384f; - representations[48].meanCosines[1] = 0.5565128318769808f; - representations[48].kappas[1] = 2.1689077268327046f; - representations[48].normalizations[1] = 0.3497620402640429f; - representations[48].weights[2] = 0.5194185702328908f; - representations[48].meanCosines[2] = 0.158735326448921f; - representations[48].kappas[2] = 0.4844120237797777f; - representations[48].normalizations[2] = 0.1242549265117551f; - representations[48].weights[3] = 0.0f; - representations[48].meanCosines[3] = 0.0f; - representations[48].kappas[3] = 0.0f; - representations[48].normalizations[3] = 0.0f; - - representations[49].K = 3; - representations[49].g = 0.3819685039370079f; - representations[49].weights[0] = 0.07557993630147046f; - representations[49].meanCosines[0] = 0.8358977483762517f; - representations[49].kappas[0] = 6.384966707199992f; - representations[49].normalizations[0] = 1.0162019040631736f; - representations[49].weights[1] = 0.40974607087036374f; - representations[49].meanCosines[1] = 0.5639876672029343f; - representations[49].kappas[1] = 2.2181095428841404f; - representations[49].normalizations[1] = 0.35725319828108354f; - representations[49].weights[2] = 0.5146739928281657f; - representations[49].meanCosines[2] = 0.16176554199961418f; - representations[49].kappas[2] = 0.49399031392292975f; - representations[49].normalizations[2] = 0.1252580573066742f; - representations[49].weights[3] = 0.0f; - representations[49].meanCosines[3] = 0.0f; - representations[49].kappas[3] = 0.0f; - representations[49].normalizations[3] = 0.0f; - - representations[50].K = 3; - representations[50].g = 0.38976377952755903f; - representations[50].weights[0] = 0.07859703707682453f; - representations[50].meanCosines[0] = 0.8405348935900007f; - representations[50].kappas[0] = 6.568178944104258f; - representations[50].normalizations[0] = 1.0453602077318829f; - representations[50].weights[1] = 0.4115447755011663f; - representations[50].meanCosines[1] = 0.5713190337485659f; - representations[50].kappas[1] = 2.2676481499650887f; - representations[50].normalizations[1] = 0.36481963932118755f; - representations[50].weights[2] = 0.5098581874220092f; - representations[50].meanCosines[2] = 0.1647823017041069f; - representations[50].kappas[2] = 0.5035454098977901f; - representations[50].normalizations[2] = 0.1262631614013433f; - representations[50].weights[3] = 0.0f; - representations[50].meanCosines[3] = 0.0f; - representations[50].kappas[3] = 0.0f; - representations[50].normalizations[3] = 0.0f; - - representations[51].K = 3; - representations[51].g = 0.39755905511811024f; - representations[51].weights[0] = 0.08171458128636552f; - representations[51].meanCosines[0] = 0.8450237123238858f; - representations[51].kappas[0] = 6.755625297772691f; - representations[51].normalizations[0] = 1.0751926173713249f; - representations[51].weights[1] = 0.41331285366521353f; - representations[51].meanCosines[1] = 0.5785106025878821f; - representations[51].kappas[1] = 2.317540949797567f; - representations[51].normalizations[1] = 0.3724629673385169f; - representations[51].weights[2] = 0.504972565048421f; - representations[51].meanCosines[2] = 0.16778567162512953f; - representations[51].kappas[2] = 0.5130776865929203f; - representations[51].normalizations[2] = 0.1272702301037747f; - representations[51].weights[3] = 0.0f; - representations[51].meanCosines[3] = 0.0f; - representations[51].kappas[3] = 0.0f; - representations[51].normalizations[3] = 0.0f; - - representations[52].K = 3; - representations[52].g = 0.4053543307086614f; - representations[52].weights[0] = 0.08493448605433432f; - representations[52].meanCosines[0] = 0.8493719674172462f; - representations[52].kappas[0] = 6.947518350251926f; - representations[52].normalizations[0] = 1.1057329088681573f; - representations[52].weights[1] = 0.4150469228659922f; - representations[52].meanCosines[1] = 0.58556609571726f; - representations[52].kappas[1] = 2.367806523563953f; - representations[52].normalizations[1] = 0.3801850217003517f; - representations[52].weights[2] = 0.5000185910796735f; - representations[52].meanCosines[2] = 0.1707757528202662f; - representations[52].kappas[2] = 0.5225876257851102f; - representations[52].normalizations[2] = 0.12827926684695073f; - representations[52].weights[3] = 0.0f; - representations[52].meanCosines[3] = 0.0f; - representations[52].kappas[3] = 0.0f; - representations[52].normalizations[3] = 0.0f; - - representations[53].K = 3; - representations[53].g = 0.4131496062992126f; - representations[53].weights[0] = 0.08825869500909991f; - representations[53].meanCosines[0] = 0.8535868936983303f; - representations[53].kappas[0] = 7.144082003779275f; - representations[53].normalizations[0] = 1.1370166735101817f; - representations[53].weights[1] = 0.4167435990709438f; - representations[53].meanCosines[1] = 0.5924892115715676f; - representations[53].kappas[1] = 2.418464235702139f; - representations[53].normalizations[1] = 0.38798781588098935f; - representations[53].weights[2] = 0.49499770591995634f; - representations[53].meanCosines[2] = 0.17375265446037172f; - representations[53].kappas[2] = 0.5320757316832715f; - representations[53].normalizations[2] = 0.12929027840892207f; - representations[53].weights[3] = 0.0f; - representations[53].meanCosines[3] = 0.0f; - representations[53].kappas[3] = 0.0f; - representations[53].normalizations[3] = 0.0f; - - representations[54].K = 3; - representations[54].g = 0.42094488188976376f; - representations[54].weights[0] = 0.09168916522716564f; - representations[54].meanCosines[0] = 0.8576752472049249f; - representations[54].kappas[0] = 7.345552722466723f; - representations[54].normalizations[0] = 1.1690815125785594f; - representations[54].weights[1] = 0.4183994860545349f; - representations[54].meanCosines[1] = 0.5992836376054463f; - representations[54].kappas[1] = 2.4695344222622806f; - representations[54].normalizations[1] = 0.3958735653601526f; - representations[54].weights[2] = 0.48991134871829956f; - representations[54].meanCosines[2] = 0.17671650241051653f; - representations[54].kappas[2] = 0.541542558806905f; - representations[54].normalizations[2] = 0.13030327794671623f; - representations[54].weights[3] = 0.0f; - representations[54].meanCosines[3] = 0.0f; - representations[54].kappas[3] = 0.0f; - representations[54].normalizations[3] = 0.0f; - - representations[55].K = 3; - representations[55].g = 0.42874015748031497f; - representations[55].weights[0] = 0.09522786839368456f; - representations[55].meanCosines[0] = 0.8616433403817125f; - representations[55].kappas[0] = 7.552180422573271f; - representations[55].normalizations[0] = 1.2019671766214413f; - representations[55].weights[1] = 0.42001117566983376f; - representations[55].meanCosines[1] = 0.6059530427287675f; - representations[55].kappas[1] = 2.5210384425501737f; - representations[55].normalizations[1] = 0.40384469461842903f; - representations[55].weights[2] = 0.48476095593648155f; - representations[55].meanCosines[2] = 0.17966743925929668f; - representations[55].kappas[2] = 0.5509887128325508f; - representations[55].normalizations[2] = 0.13131828519299638f; - representations[55].weights[3] = 0.0f; - representations[55].meanCosines[3] = 0.0f; - representations[55].kappas[3] = 0.0f; - representations[55].normalizations[3] = 0.0f; - - representations[56].K = 3; - representations[56].g = 0.4365354330708661f; - representations[56].weights[0] = 0.0988767934663242f; - representations[56].meanCosines[0] = 0.8654970737530904f; - representations[56].kappas[0] = 7.764229399563398f; - representations[56].normalizations[0] = 1.2357157110806771f; - representations[56].weights[1] = 0.42157524842882677f; - representations[56].meanCosines[1] = 0.612501068934138f; - representations[56].kappas[1] = 2.5729987214001024f; - representations[56].normalizations[1] = 0.4119038426292747f; - representations[56].weights[2] = 0.47954795810484907f; - representations[56].meanCosines[2] = 0.18260562362373325f; - representations[56].kappas[2] = 0.5604148491400338f; - representations[56].normalizations[2] = 0.1323353264040619f; - representations[56].weights[3] = 0.0f; - representations[56].meanCosines[3] = 0.0f; - representations[56].kappas[3] = 0.0f; - representations[56].normalizations[3] = 0.0f; - - representations[57].K = 3; - representations[57].g = 0.44433070866141733f; - representations[57].weights[0] = 0.10263796004725238f; - representations[57].meanCosines[0] = 0.8692419595769955f; - representations[57].kappas[0] = 7.981979001500163f; - representations[57].normalizations[0] = 1.270371561952546f; - representations[57].weights[1] = 0.42308827723445225f; - representations[57].meanCosines[1] = 0.6189313112296096f; - representations[57].kappas[1] = 2.6254386902453777f; - representations[57].normalizations[1] = 0.4200538525478618f; - representations[57].weights[2] = 0.47427376271829536f; - representations[57].meanCosines[2] = 0.18553122367844202f; - representations[57].kappas[2] = 0.5698216527617949f; - representations[57].normalizations[2] = 0.1333544322829776f; - representations[57].weights[3] = 0.0f; - representations[57].meanCosines[3] = 0.0f; - representations[57].kappas[3] = 0.0f; - representations[57].normalizations[3] = 0.0f; - - representations[58].K = 3; - representations[58].g = 0.4521259842519685f; - representations[58].weights[0] = 0.10651340265267141f; - representations[58].meanCosines[0] = 0.8728831598504667f; - representations[58].kappas[0] = 8.20572532527276f; - representations[58].normalizations[0] = 1.3059818445660667f; - representations[58].weights[1] = 0.4245468183339547f; - representations[58].meanCosines[1] = 0.6252473352033313f; - representations[58].kappas[1] = 2.6783830265653674f; - representations[58].normalizations[1] = 0.42829780768018394f; - representations[58].weights[2] = 0.4689397790133738f; - representations[58].meanCosines[2] = 0.18844442736311248f; - representations[58].kappas[2] = 0.5792098718805595f; - representations[58].normalizations[2] = 0.13437564168445362f; - representations[58].weights[3] = 0.0f; - representations[58].meanCosines[3] = 0.0f; - representations[58].kappas[3] = 0.0f; - representations[58].normalizations[3] = 0.0f; - - representations[59].K = 3; - representations[59].g = 0.4599212598425197f; - representations[59].weights[0] = 0.11050517555935604f; - representations[59].meanCosines[0] = 0.8764255095007417f; - representations[59].kappas[0] = 8.435782379970613f; - representations[59].normalizations[0] = 1.342596527819977f; - representations[59].weights[1] = 0.42594741240052664f; - representations[59].meanCosines[1] = 0.6314526684925892f; - representations[59].kappas[1] = 2.7318576950764704f; - representations[59].normalizations[1] = 0.436639036804549f; - representations[59].weights[2] = 0.4635474120401174f; - representations[59].meanCosines[2] = 0.1913454408889863f; - representations[59].kappas[2] = 0.5885803139592967f; - representations[59].normalizations[2] = 0.13539900131670243f; - representations[59].weights[3] = 0.0f; - representations[59].meanCosines[3] = 0.0f; - representations[59].kappas[3] = 0.0f; - representations[59].normalizations[3] = 0.0f; - - representations[60].K = 3; - representations[60].g = 0.46771653543307085f; - representations[60].weights[0] = 0.11461533860200686f; - representations[60].meanCosines[0] = 0.8798735470937176f; - representations[60].kappas[0] = 8.672483998747186f; - representations[60].normalizations[0] = 1.3802687377565923f; - representations[60].weights[1] = 0.42728658030803607f; - representations[60].meanCosines[1] = 0.6375508149620032f; - representations[60].kappas[1] = 2.7858901874628623f; - representations[60].normalizations[1] = 0.4450811504792057f; - representations[60].weights[2] = 0.45809808108995725f; - representations[60].meanCosines[2] = 0.19423449766964776f; - representations[60].kappas[2] = 0.5979338756232817f; - representations[60].normalizations[2] = 0.13642456913873516f; - representations[60].weights[3] = 0.0f; - representations[60].meanCosines[3] = 0.0f; - representations[60].kappas[3] = 0.0f; - representations[60].normalizations[3] = 0.0f; - - representations[61].K = 3; - representations[61].g = 0.47551181102362206f; - representations[61].weights[0] = 0.11884599637104817f; - representations[61].meanCosines[0] = 0.8832315179423937f; - representations[61].kappas[0] = 8.916184139359721f; - representations[61].normalizations[0] = 1.419054804853077f; - representations[61].weights[1] = 0.4285608327734269f; - representations[61].meanCosines[1] = 0.6435452084762158f; - representations[61].kappas[1] = 2.8405092323844556f; - representations[61].normalizations[1] = 0.4536279946281f; - representations[61].weights[2] = 0.4525931708555248f; - representations[61].meanCosines[2] = 0.19711183827311177f; - representations[61].kappas[2] = 0.6072714788289457f; - representations[61].normalizations[2] = 0.1374524074966876f; - representations[61].weights[3] = 0.0f; - representations[61].meanCosines[3] = 0.0f; - representations[61].kappas[3] = 0.0f; - representations[61].normalizations[3] = 0.0f; - - representations[62].K = 3; - representations[62].g = 0.4833070866141732f; - representations[62].weights[0] = 0.12319928766759637f; - representations[62].meanCosines[0] = 0.8865034015121176f; - representations[62].kappas[0] = 9.16725893612397f; - representations[62].normalizations[0] = 1.4590145901905027f; - representations[62].weights[1] = 0.42976666301618144f; - representations[62].meanCosines[1] = 0.6494392269329624f; - representations[62].kappas[1] = 2.8957450141747496f; - representations[62].normalizations[1] = 0.46228368338595593f; - representations[62].weights[2] = 0.44703404931622226f; - representations[62].meanCosines[2] = 0.19997771817476762f; - representations[62].kappas[2] = 0.616594096682104f; - representations[62].normalizations[2] = 0.13848258601896915f; - representations[62].weights[3] = 0.0f; - representations[62].meanCosines[3] = 0.0f; - representations[62].kappas[3] = 0.0f; - representations[62].normalizations[3] = 0.0f; - - representations[63].K = 3; - representations[63].g = 0.4911023622047244f; - representations[63].weights[0] = 0.12767711326081116f; - representations[63].meanCosines[0] = 0.8896930424203258f; - representations[63].kappas[0] = 9.426117857395496f; - representations[63].normalizations[0] = 1.500213260915139f; - representations[63].weights[1] = 0.4309005122013021f; - representations[63].meanCosines[1] = 0.6552364769534045f; - representations[63].kappas[1] = 2.9516320648387557f; - representations[63].normalizations[1] = 0.471053051906239f; - representations[63].weights[2] = 0.44142237453788674f; - representations[63].meanCosines[2] = 0.20283255209471382f; - representations[63].kappas[2] = 0.6259032255561982f; - representations[63].normalizations[2] = 0.13951523417822578f; - representations[63].weights[3] = 0.0f; - representations[63].meanCosines[3] = 0.0f; - representations[63].kappas[3] = 0.0f; - representations[63].normalizations[3] = 0.0f; - - representations[64].K = 3; - representations[64].g = 0.4988976377952756f; - representations[64].weights[0] = 0.13228217893070182f; - representations[64].meanCosines[0] = 0.8928037371351293f; - representations[64].kappas[0] = 9.693170363545615f; - representations[64].normalizations[0] = 1.5427159834637596f; - representations[64].weights[1] = 0.43195889896389156f; - representations[64].meanCosines[1] = 0.6609397021872523f; - representations[64].kappas[1] = 3.0081987975922257f; - representations[64].normalizations[1] = 0.47994001241960793f; - representations[64].weights[2] = 0.43575892210540673f; - representations[64].meanCosines[2] = 0.20567636859603608f; - representations[64].kappas[2] = 0.6351991067898674f; - representations[64].normalizations[2] = 0.14055034398422908f; - representations[64].weights[3] = 0.0f; - representations[64].meanCosines[3] = 0.0f; - representations[64].kappas[3] = 0.0f; - representations[64].normalizations[3] = 0.0f; - - representations[65].K = 3; - representations[65].g = 0.5066929133858268f; - representations[65].weights[0] = 0.13701645780490154f; - representations[65].meanCosines[0] = 0.8958388925416747f; - representations[65].kappas[0] = 9.968880275772742f; - representations[65].normalizations[0] = 1.5865965764607521f; - representations[65].weights[1] = 0.43293821041468983f; - representations[65].meanCosines[1] = 0.6665524055023117f; - representations[65].kappas[1] = 3.0654832705645223f; - representations[65].normalizations[1] = 0.4889500266604984f; - representations[65].weights[2] = 0.4300453317804087f; - representations[65].meanCosines[2] = 0.20850962101611986f; - representations[65].kappas[2] = 0.6444833721001508f; - representations[65].normalizations[2] = 0.14158806355836523f; - representations[65].weights[3] = 0.0f; - representations[65].meanCosines[3] = 0.0f; - representations[65].kappas[3] = 0.0f; - representations[65].normalizations[3] = 0.0f; - - representations[66].K = 3; - representations[66].g = 0.5144881889763779f; - representations[66].weights[0] = 0.14188167518350953f; - representations[66].meanCosines[0] = 0.8988018020497218f; - representations[66].kappas[0] = 10.253752777050046f; - representations[66].normalizations[0] = 1.6319354417346774f; - representations[66].weights[1] = 0.4338348440662771f; - representations[66].meanCosines[1] = 0.672078283990385f; - representations[66].kappas[1] = 3.123528477106368f; - representations[66].normalizations[1] = 0.498089369724428f; - representations[66].weights[2] = 0.42428348075021344f; - representations[66].meanCosines[2] = 0.21133292088157304f; - representations[66].kappas[2] = 0.6537581843157421f; - representations[66].normalizations[2] = 0.14262860345015743f; - representations[66].weights[3] = 0.0f; - representations[66].meanCosines[3] = 0.0f; - representations[66].kappas[3] = 0.0f; - representations[66].normalizations[3] = 0.0f; - - representations[67].K = 3; - representations[67].g = 0.5222834645669291f; - representations[67].weights[0] = 0.14688190532912504f; - representations[67].meanCosines[0] = 0.9016947510325678f; - representations[67].kappas[0] = 10.548244803107089f; - representations[67].normalizations[0] = 1.6788053025137655f; - representations[67].weights[1] = 0.4346451786272443f; - representations[67].meanCosines[1] = 0.6775187639861546f; - representations[67].kappas[1] = 3.18235586208853f; - representations[67].normalizations[1] = 0.5073609548705329f; - representations[67].weights[2] = 0.41847291604363074f; - representations[67].meanCosines[2] = 0.21414573980230114f; - representations[67].kappas[2] = 0.6630219638878598f; - representations[67].normalizations[2] = 0.14367175560038878f; - representations[67].weights[3] = 0.0f; - representations[67].meanCosines[3] = 0.0f; - representations[67].kappas[3] = 0.0f; - representations[67].normalizations[3] = 0.0f; - - representations[68].K = 3; - representations[68].g = 0.5300787401574802f; - representations[68].weights[0] = 0.15201802364423217f; - representations[68].meanCosines[0] = 0.9045210208344292f; - representations[68].kappas[0] = 10.852964167601495f; - representations[68].normalizations[0] = 1.7273028951195475f; - representations[68].weights[1] = 0.435365524307831f; - representations[68].meanCosines[1] = 0.6828783513636263f; - representations[68].kappas[1] = 3.2420223660584204f; - representations[68].normalizations[1] = 0.5167733180958464f; - representations[68].weights[2] = 0.41261645204793684f; - representations[68].meanCosines[2] = 0.2169492083133833f; - representations[68].kappas[2] = 0.6722785944850328f; - representations[68].normalizations[2] = 0.14471792788382354f; - representations[68].weights[3] = 0.0f; - representations[68].meanCosines[3] = 0.0f; - representations[68].kappas[3] = 0.0f; - representations[68].normalizations[3] = 0.0f; - - representations[69].K = 3; - representations[69].g = 0.5378740157480315f; - representations[69].weights[0] = 0.15729294132110566f; - representations[69].meanCosines[0] = 0.9072830203855161f; - representations[69].kappas[0] = 11.168487946406515f; - representations[69].normalizations[0] = 1.7775200638868365f; - representations[69].weights[1] = 0.43599216989551043f; - representations[69].meanCosines[1] = 0.6881595863609994f; - representations[69].kappas[1] = 3.3025669779058386f; - representations[69].normalizations[1] = 0.5263321984049527f; - representations[69].weights[2] = 0.4067148887833839f; - representations[69].meanCosines[2] = 0.21974347919085768f; - representations[69].kappas[2] = 0.6815287539431827f; - representations[69].normalizations[2] = 0.1457671702417904f; - representations[69].weights[3] = 0.0f; - representations[69].meanCosines[3] = 0.0f; - representations[69].kappas[3] = 0.0f; - representations[69].normalizations[3] = 0.0f; - - representations[70].K = 3; - representations[70].g = 0.5456692913385827f; - representations[70].weights[0] = 0.1627091674945393f; - representations[70].meanCosines[0] = 0.9099831724121029f; - representations[70].kappas[0] = 11.495452369732478f; - representations[70].normalizations[0] = 1.8295580679098282f; - representations[70].weights[1] = 0.43652135984600265f; - representations[70].meanCosines[1] = 0.6933653968776663f; - representations[70].kappas[1] = 3.364035938949523f; - representations[70].normalizations[1] = 0.5360445070649383f; - representations[70].weights[2] = 0.40076947265945795f; - representations[70].meanCosines[2] = 0.22252895888323956f; - representations[70].kappas[2] = 0.690773965537422f; - representations[70].normalizations[2] = 0.1468196300804049f; - representations[70].weights[3] = 0.0f; - representations[70].meanCosines[3] = 0.0f; - representations[70].kappas[3] = 0.0f; - representations[70].normalizations[3] = 0.0f; - - representations[71].K = 3; - representations[71].g = 0.5534645669291338f; - representations[71].weights[0] = 0.16826931509786597f; - representations[71].meanCosines[0] = 0.9126237466462465f; - representations[71].kappas[0] = 11.834538906133483f; - representations[71].normalizations[0] = 1.883525366223493f; - representations[71].weights[1] = 0.436949287161954f; - representations[71].meanCosines[1] = 0.6984986216586416f; - representations[71].kappas[1] = 3.426477782827816f; - representations[71].normalizations[1] = 0.545917545079653f; - representations[71].weights[2] = 0.39478139774018f; - representations[71].meanCosines[2] = 0.22530605709251292f; - representations[71].kappas[2] = 0.7000157749339841f; - representations[71].normalizations[2] = 0.14787545977774874f; - representations[71].weights[3] = 0.0f; - representations[71].meanCosines[3] = 0.0f; - representations[71].kappas[3] = 0.0f; - representations[71].normalizations[3] = 0.0f; - - representations[72].K = 3; - representations[72].g = 0.561259842519685f; - representations[72].weights[0] = 0.17397605681486036f; - representations[72].meanCosines[0] = 0.91520688470064f; - representations[72].kappas[0] = 12.186480389405208f; - representations[72].normalizations[0] = 1.9395385929167108f; - representations[72].weights[1] = 0.4372720921624159f; - representations[72].meanCosines[1] = 0.7035620560829642f; - representations[72].kappas[1] = 3.4899440461679654f; - representations[72].normalizations[1] = 0.555959114489885f; - representations[72].weights[2] = 0.3887518510227237f; - representations[72].meanCosines[2] = 0.22807521187546123f; - representations[72].kappas[2] = 0.7092558347125714f; - representations[72].normalizations[2] = 0.1489348264074376f; - representations[72].weights[3] = 0.0f; - representations[72].meanCosines[3] = 0.0f; - representations[72].kappas[3] = 0.0f; - representations[72].normalizations[3] = 0.0f; - - representations[73].K = 3; - representations[73].g = 0.5690551181102362f; - representations[73].weights[0] = 0.17983214378421922f; - representations[73].meanCosines[0] = 0.9177346040817985f; - representations[73].kappas[0] = 12.552065355633442f; - representations[73].normalizations[0] = 1.997723247386592f; - representations[73].weights[1] = 0.4374858568977017f; - representations[73].meanCosines[1] = 0.7085584413162697f; - representations[73].kappas[1] = 3.554489351229144f; - representations[73].normalizations[1] = 0.5661775306041705f; - representations[73].weights[2] = 0.38268199931807917f; - representations[73].meanCosines[2] = 0.23083688408868736f; - representations[73].kappas[2] = 0.7184958875618854f; - representations[73].normalizations[2] = 0.1499979099875054f; - representations[73].weights[3] = 0.0f; - representations[73].meanCosines[3] = 0.0f; - representations[73].kappas[3] = 0.0f; - representations[73].normalizations[3] = 0.0f; - - representations[74].K = 3; - representations[74].g = 0.5768503937007874f; - representations[74].weights[0] = 0.1858404095572948f; - representations[74].meanCosines[0] = 0.9202088063452304f; - representations[74].kappas[0] = 12.93214347991311f; - representations[74].normalizations[0] = 2.0582145596138406f; - representations[74].weights[1] = 0.4375866002297341f; - representations[74].meanCosines[1] = 0.7134904673435183f; - representations[74].kappas[1] = 3.620171668163421f; - representations[74].normalizations[1] = 0.5765816626610434f; - representations[74].weights[2] = 0.376572990212971f; - representations[74].meanCosines[2] = 0.23359155944610333f; - representations[74].kappas[2] = 0.7277377748041182f; - representations[74].normalizations[2] = 0.15106490461580072f; - representations[74].weights[3] = 0.0f; - representations[74].meanCosines[3] = 0.0f; - representations[74].kappas[3] = 0.0f; - representations[74].normalizations[3] = 0.0f; - - representations[75].K = 3; - representations[75].g = 0.5846456692913385f; - representations[75].weights[0] = 0.1920037740311606f; - representations[75].meanCosines[0] = 0.9226312846743214f; - representations[75].kappas[0] = 13.327631663072642f; - representations[75].normalizations[0] = 2.1211584588916965f; - representations[75].weights[1] = 0.4375702730069559f; - representations[75].meanCosines[1] = 0.7183607762114199f; - representations[75].kappas[1] = 3.68705260568459f; - representations[75].normalizations[1] = 0.587180979062321f; - representations[75].weights[2] = 0.3704259529618835f; - representations[75].meanCosines[2] = 0.23633975076704322f; - representations[75].kappas[2] = 0.7369834457308975f; - representations[75].normalizations[2] = 0.15213601971801666f; - representations[75].weights[3] = 0.0f; - representations[75].meanCosines[3] = 0.0f; - representations[75].kappas[3] = 0.0f; - representations[75].normalizations[3] = 0.0f; - - representations[76].K = 3; - representations[76].g = 0.5924409448818897f; - representations[76].weights[0] = 0.19832522506414976f; - representations[76].meanCosines[0] = 0.9250037361138848f; - representations[76].kappas[0] = 13.739521789305007f; - representations[76].normalizations[0] = 2.1867128084892404f; - representations[76].weights[1] = 0.43743275979935015f; - representations[76].meanCosines[1] = 0.7231719821313055f; - representations[76].kappas[1] = 3.755197973339379f; - representations[76].normalizations[1] = 0.5979856357457428f; - representations[76].weights[2] = 0.3642420151365001f; - representations[76].meanCosines[2] = 0.23908201028376885f; - representations[76].kappas[2] = 0.7462350011130275f; - representations[76].normalizations[2] = 0.15321148529531584f; - representations[76].weights[3] = 0.0f; - representations[76].meanCosines[3] = 0.0f; - representations[76].kappas[3] = 0.0f; - representations[76].normalizations[3] = 0.0f; - - representations[77].K = 3; - representations[77].g = 0.600236220472441f; - representations[77].weights[0] = 0.2046370452946239f; - representations[77].meanCosines[0] = 0.9273696065000837f; - representations[77].kappas[0] = 14.176868423187258f; - representations[77].normalizations[0] = 2.2563186871147516f; - representations[77].weights[1] = 0.43734456589562715f; - representations[77].meanCosines[1] = 0.7279873281080078f; - representations[77].kappas[1] = 3.82557869797969f; - representations[77].normalizations[1] = 0.6091494065393616f; - representations[77].weights[2] = 0.35801838880974884f; - representations[77].meanCosines[2] = 0.2418089043788005f; - representations[77].kappas[2] = 0.7554607295835146f; - representations[77].normalizations[2] = 0.15428758395409456f; - representations[77].weights[3] = 0.0f; - representations[77].meanCosines[3] = 0.0f; - representations[77].kappas[3] = 0.0f; - representations[77].normalizations[3] = 0.0f; - - representations[78].K = 3; - representations[78].g = 0.6080314960629921f; - representations[78].weights[0] = 0.21145522532501376f; - representations[78].meanCosines[0] = 0.9296047853907953f; - representations[78].kappas[0] = 14.61687501213509f; - representations[78].normalizations[0] = 2.3263479107381757f; - representations[78].weights[1] = 0.43677719515994007f; - representations[78].meanCosines[1] = 0.732627039434998f; - representations[78].kappas[1] = 3.8955627628160325f; - representations[78].normalizations[1] = 0.6202544751769821f; - representations[78].weights[2] = 0.35176757951504606f; - representations[78].meanCosines[2] = 0.24455092610935678f; - representations[78].kappas[2] = 0.7647642149394f; - representations[78].normalizations[2] = 0.15537640901792682f; - representations[78].weights[3] = 0.0f; - representations[78].meanCosines[3] = 0.0f; - representations[78].kappas[3] = 0.0f; - representations[78].normalizations[3] = 0.0f; - - representations[79].K = 3; - representations[79].g = 0.6158267716535433f; - representations[79].weights[0] = 0.21827030956844096f; - representations[79].meanCosines[0] = 0.9318363148472478f; - representations[79].kappas[0] = 15.0847624352229f; - representations[79].normalizations[0] = 2.400814506932851f; - representations[79].weights[1] = 0.4362504726325965f; - representations[79].meanCosines[1] = 0.7372758864789994f; - representations[79].kappas[1] = 3.9679362147525175f; - representations[79].normalizations[1] = 0.6317426240166054f; - representations[79].weights[2] = 0.3454792177989626f; - representations[79].meanCosines[2] = 0.24727883164854889f; - representations[79].kappas[2] = 0.7740466736698095f; - representations[79].normalizations[2] = 0.15646641319686902f; - representations[79].weights[3] = 0.0f; - representations[79].meanCosines[3] = 0.0f; - representations[79].kappas[3] = 0.0f; - representations[79].normalizations[3] = 0.0f; - - representations[80].K = 3; - representations[80].g = 0.6236220472440944f; - representations[80].weights[0] = 0.22525660341537493f; - representations[80].meanCosines[0] = 0.9340236772779147f; - representations[80].kappas[0] = 15.573919583003752f; - representations[80].normalizations[0] = 2.47866628495079f; - representations[80].weights[1] = 0.43558520774587756f; - representations[80].meanCosines[1] = 0.741875590576798f; - representations[80].kappas[1] = 4.0418826507574455f; - representations[80].normalizations[1] = 0.6434841227651966f; - representations[80].weights[2] = 0.3391581888387475f; - representations[80].meanCosines[2] = 0.25000328942163386f; - representations[80].kappas[2] = 0.7833445758656036f; - representations[80].normalizations[2] = 0.15756185584196966f; - representations[80].weights[3] = 0.0f; - representations[80].meanCosines[3] = 0.0f; - representations[80].kappas[3] = 0.0f; - representations[80].normalizations[3] = 0.0f; - - representations[81].K = 3; - representations[81].g = 0.6314173228346457f; - representations[81].weights[0] = 0.23241776175313703f; - representations[81].meanCosines[0] = 0.9361681219135087f; - representations[81].kappas[0] = 16.085837543042345f; - representations[81].normalizations[0] = 2.560140558748405f; - representations[81].weights[1] = 0.43477678714167f; - representations[81].meanCosines[1] = 0.7464284999133005f; - representations[81].kappas[1] = 4.117492199043666f; - representations[81].normalizations[1] = 0.6554930806692963f; - representations[81].weights[2] = 0.3328054511051931f; - representations[81].meanCosines[2] = 0.25272498180459707f; - representations[81].kappas[2] = 0.7926605874210905f; - representations[81].normalizations[2] = 0.15866305057516353f; - representations[81].weights[3] = 0.0f; - representations[81].meanCosines[3] = 0.0f; - representations[81].kappas[3] = 0.0f; - representations[81].normalizations[3] = 0.0f; - - representations[82].K = 3; - representations[82].g = 0.6392125984251968f; - representations[82].weights[0] = 0.23975751170874146f; - representations[82].meanCosines[0] = 0.938270840447678f; - representations[82].kappas[0] = 16.622146439652063f; - representations[82].normalizations[0] = 2.6454967706679846f; - representations[82].weights[1] = 0.4338205035338164f; - representations[82].meanCosines[1] = 0.7509369787660656f; - representations[82].kappas[1] = 4.19486225496789f; - representations[82].normalizations[1] = 0.6677847773966972f; - representations[82].weights[2] = 0.326421984757442f; - representations[82].meanCosines[2] = 0.2554446622503517f; - representations[82].kappas[2] = 0.8019976488252991f; - representations[82].normalizations[2] = 0.15977034747756208f; - representations[82].weights[3] = 0.0f; - representations[82].meanCosines[3] = 0.0f; - representations[82].kappas[3] = 0.0f; - representations[82].normalizations[3] = 0.0f; - - representations[83].K = 3; - representations[83].g = 0.647007874015748f; - representations[83].weights[0] = 0.2472797267392922f; - representations[83].meanCosines[0] = 0.9403329568840185f; - representations[83].kappas[0] = 17.184628287927787f; - representations[83].normalizations[0] = 2.735018537220525f; - representations[83].weights[1] = 0.4327115257623153f; - representations[83].meanCosines[1] = 0.755403364106f; - representations[83].kappas[1] = 4.274097395549266f; - representations[83].normalizations[1] = 0.6803756490612852f; - representations[83].weights[2] = 0.32000874749839253f; - representations[83].meanCosines[2] = 0.25816313034840566f; - representations[83].kappas[2] = 0.8113588939736538f; - representations[83].normalizations[2] = 0.16088412390685938f; - representations[83].weights[3] = 0.0f; - representations[83].meanCosines[3] = 0.0f; - representations[83].kappas[3] = 0.0f; - representations[83].normalizations[3] = 0.0f; - - representations[84].K = 3; - representations[84].g = 0.6548031496062992f; - representations[84].weights[0] = 0.25498843647079295f; - representations[84].meanCosines[0] = 0.9423555310229852f; - representations[84].kappas[0] = 17.775234863783915f; - representations[84].normalizations[0] = 2.8290164931906037f; - representations[84].weights[1] = 0.4314448895810194f; - representations[84].meanCosines[1] = 0.7598299689358737f; - representations[84].kappas[1] = 4.3553100825444515f; - representations[84].normalizations[1] = 0.6932833994669038f; - representations[84].weights[2] = 0.31356667394818777f; - representations[84].meanCosines[2] = 0.26088123558629017f; - representations[84].kappas[2] = 0.8207476668897828f; - representations[84].normalizations[2] = 0.1620047868302051f; - representations[84].weights[3] = 0.0f; - representations[84].meanCosines[3] = 0.0f; - representations[84].kappas[3] = 0.0f; - representations[84].normalizations[3] = 0.0f; - - representations[85].K = 3; - representations[85].g = 0.6625984251968504f; - representations[85].weights[0] = 0.26288783702158497f; - representations[85].meanCosines[0] = 0.9443395617200645f; - representations[85].kappas[0] = 18.396108136191025f; - representations[85].normalizations[0] = 2.927831543527836f; - representations[85].weights[1] = 0.43001548795721395f; - representations[85].meanCosines[1] = 0.7642190859151877f; - representations[85].kappas[1] = 4.438621453366375f; - representations[85].normalizations[1] = 0.7065271253657252f; - representations[85].weights[2] = 0.3070966750212011f; - representations[85].meanCosines[2] = 0.26359988157208303f; - representations[85].kappas[2] = 0.8301675404574355f; - representations[85].normalizations[2] = 0.1631327754356981f; - representations[85].weights[3] = 0.0f; - representations[85].meanCosines[3] = 0.0f; - representations[85].kappas[3] = 0.0f; - representations[85].normalizations[3] = 0.0f; - - representations[86].K = 3; - representations[86].g = 0.6703937007874016f; - representations[86].weights[0] = 0.2709823025842266f; - representations[86].meanCosines[0] = 0.946285989794297f; - representations[86].kappas[0] = 19.04960365116869f; - representations[86].normalizations[0] = 3.0318385850249148f; - representations[86].weights[1] = 0.42841806009583794f; - representations[86].meanCosines[1] = 0.7685729910925694f; - representations[86].kappas[1] = 4.524162209037049f; - representations[86].normalizations[1] = 0.7201274571932929f; - representations[86].weights[2] = 0.30059963731993555f; - representations[86].meanCosines[2] = 0.26632003080603134f; - representations[86].kappas[2] = 0.8396223375305958f; - representations[86].normalizations[2] = 0.1642685640724313f; - representations[86].weights[3] = 0.0f; - representations[86].meanCosines[3] = 0.0f; - representations[86].kappas[3] = 0.0f; - representations[86].normalizations[3] = 0.0f; - - representations[87].K = 3; - representations[87].g = 0.6781889763779527f; - representations[87].weights[0] = 0.27927639895625234f; - representations[87].meanCosines[0] = 0.9481957005904299f; - representations[87].kappas[0] = 19.738317362685333f; - representations[87].normalizations[0] = 3.141450776587954f; - representations[87].weights[1] = 0.42664717956103104f; - representations[87].meanCosines[1] = 0.7728939469951241f; - representations[87].kappas[1] = 4.6120735976093465f; - representations[87].normalizations[1] = 0.7341067150314727f; - representations[87].weights[2] = 0.2940764214827166f; - representations[87].meanCosines[2] = 0.26904270916915274f; - representations[87].kappas[2] = 0.8491161515891782f; - representations[87].normalizations[2] = 0.16541266518389522f; - representations[87].weights[3] = 0.0f; - representations[87].meanCosines[3] = 0.0f; - representations[87].kappas[3] = 0.0f; - representations[87].normalizations[3] = 0.0f; - - representations[88].K = 3; - representations[88].g = 0.6859842519685039f; - representations[88].weights[0] = 0.28777489737254797f; - representations[88].meanCosines[0] = 0.950069526417547f; - representations[88].kappas[0] = 20.46511658959084f; - representations[88].normalizations[0] = 3.257124466185333f; - representations[88].weights[1] = 0.4246972411959944f; - representations[88].meanCosines[1] = 0.777184206751141f; - representations[88].kappas[1] = 4.702508541381448f; - representations[88].normalizations[1] = 0.7484890874829961f; - representations[88].weights[2] = 0.2875278614314578f; - representations[88].meanCosines[2] = 0.27176901175720886f; - representations[88].kappas[2] = 0.8586533726595088f; - representations[88].normalizations[2] = 0.16656563292649454f; - representations[88].weights[3] = 0.0f; - representations[88].meanCosines[3] = 0.0f; - representations[88].kappas[3] = 0.0f; - representations[88].normalizations[3] = 0.0f; - - representations[89].K = 3; - representations[89].g = 0.6937795275590551f; - representations[89].weights[0] = 0.29648279054616156f; - representations[89].meanCosines[0] = 0.9519082486667635f; - representations[89].kappas[0] = 21.233175767008145f; - representations[89].normalizations[0] = 3.3793648808583927f; - representations[89].weights[1] = 0.42256244663705916f; - representations[89].meanCosines[1] = 0.7814460177839457f; - representations[89].kappas[1] = 4.79563289895453f; - representations[89].normalizations[1] = 0.7633008320368476f; - representations[89].weights[2] = 0.2809547628167793f; - representations[89].meanCosines[2] = 0.27450010877501546f; - representations[89].kappas[2] = 0.8682387141297602f; - representations[89].normalizations[2] = 0.16772806695708195f; - representations[89].weights[3] = 0.0f; - representations[89].meanCosines[3] = 0.0f; - representations[89].kappas[3] = 0.0f; - representations[89].normalizations[3] = 0.0f; - - representations[90].K = 3; - representations[90].g = 0.7015748031496063f; - representations[90].weights[0] = 0.30540725904987076f; - representations[90].meanCosines[0] = 0.9537123443474214f; - representations[90].kappas[0] = 22.04589839813786f; - representations[90].normalizations[0] = 3.508713704965338f; - representations[90].weights[1] = 0.4202357317039357f; - representations[90].meanCosines[1] = 0.7856805379542191f; - representations[90].kappas[1] = 4.891601785632994f; - representations[90].normalizations[1] = 0.7785665078511023f; - representations[90].weights[2] = 0.27435700924619355f; - representations[90].meanCosines[2] = 0.27723648769685544f; - representations[90].kappas[2] = 0.8778745463929781f; - representations[90].normalizations[2] = 0.16890028814166394f; - representations[90].weights[3] = 0.0f; - representations[90].meanCosines[3] = 0.0f; - representations[90].kappas[3] = 0.0f; - representations[90].normalizations[3] = 0.0f; - - representations[91].K = 3; - representations[91].g = 0.7093700787401575f; - representations[91].weights[0] = 0.314550142879425f; - representations[91].meanCosines[0] = 0.9554829884712971f; - representations[91].kappas[0] = 22.907423174275007f; - representations[91].normalizations[0] = 3.645829631683703f; - representations[91].weights[1] = 0.41771281013698197f; - representations[91].meanCosines[1] = 0.7898920757285216f; - representations[91].kappas[1] = 4.990657929218684f; - representations[91].normalizations[1] = 0.7943246211247126f; - representations[91].weights[2] = 0.2677370469835929f; - representations[91].meanCosines[2] = 0.2799809273695421f; - representations[91].kappas[2] = 0.887571384710121f; - representations[91].normalizations[2] = 0.1700836159252505f; - representations[91].weights[3] = 0.0f; - representations[91].meanCosines[3] = 0.0f; - representations[91].kappas[3] = 0.0f; - representations[91].normalizations[3] = 0.0f; - - representations[92].K = 3; - representations[92].g = 0.7171653543307086f; - representations[92].weights[0] = 0.323918941281032f; - representations[92].meanCosines[0] = 0.9572205847121196f; - representations[92].kappas[0] = 23.822020537466877f; - representations[92].normalizations[0] = 3.791392322974503f; - representations[92].weights[1] = 0.41498628744100596f; - representations[92].meanCosines[1] = 0.7940819034205951f; - representations[92].kappas[1] = 5.092993495012177f; - representations[92].normalizations[1] = 0.8106056455269498f; - representations[92].weights[2] = 0.2610947712779621f; - representations[92].meanCosines[2] = 0.282734183473497f; - representations[92].kappas[2] = 0.8973327073543883f; - representations[92].normalizations[2] = 0.17127852245500216f; - representations[92].weights[3] = 0.0f; - representations[92].meanCosines[3] = 0.0f; - representations[92].kappas[3] = 0.0f; - representations[92].normalizations[3] = 0.0f; - - representations[93].K = 3; - representations[93].g = 0.7249606299212599f; - representations[93].weights[0] = 0.33351973492144515f; - representations[93].meanCosines[0] = 0.9589257276203178f; - representations[93].kappas[0] = 24.794582197555773f; - representations[93].normalizations[0] = 3.9461803186393105f; - representations[93].weights[1] = 0.4120494090831267f; - representations[93].meanCosines[1] = 0.7982522854579217f; - representations[93].kappas[1] = 5.198842429689294f; - representations[93].normalizations[1] = 0.8274467106645826f; - representations[93].weights[2] = 0.2544308559954282f; - representations[93].meanCosines[2] = 0.28549779909773215f; - representations[93].kappas[2] = 0.9071648530197196f; - representations[93].normalizations[2] = 0.17248583639675724f; - representations[93].weights[3] = 0.0f; - representations[93].meanCosines[3] = 0.0f; - representations[93].kappas[3] = 0.0f; - representations[93].normalizations[3] = 0.0f; - - representations[94].K = 3; - representations[94].g = 0.732755905511811f; - representations[94].weights[0] = 0.34335893848221183f; - representations[94].meanCosines[0] = 0.9605989682723478f; - representations[94].kappas[0] = 25.830596813856708f; - representations[94].normalizations[0] = 4.111067165939057f; - representations[94].weights[1] = 0.4088951248319031f; - representations[94].meanCosines[1] = 0.8024055019653422f; - representations[94].kappas[1] = 5.308461053986367f; - representations[94].normalizations[1] = 0.844888514968835f; - representations[94].weights[2] = 0.24774593668588507f; - representations[94].meanCosines[2] = 0.28827343354031715f; - representations[94].kappas[2] = 0.9170746723463243f; - representations[94].normalizations[2] = 0.17370645864779166f; - representations[94].weights[3] = 0.0f; - representations[94].meanCosines[3] = 0.0f; - representations[94].kappas[3] = 0.0f; - representations[94].normalizations[3] = 0.0f; - - representations[95].K = 3; - representations[95].g = 0.7405511811023622f; - representations[95].weights[0] = 0.3534433331276196f; - representations[95].meanCosines[0] = 0.9622408150553718f; - representations[95].kappas[0] = 26.936241870352298f; - representations[95].normalizations[0] = 4.2870360419854485f; - representations[95].weights[1] = 0.4055160595500465f; - representations[95].meanCosines[1] = 0.8065438531577983f; - representations[95].kappas[1] = 5.4221308324173805f; - representations[95].normalizations[1] = 0.862975766145269f; - representations[95].weights[2] = 0.241040607322334f; - representations[95].meanCosines[2] = 0.29106287302029366f; - representations[95].kappas[2] = 0.9270695781955348f; - representations[95].normalizations[2] = 0.1749413695318436f; - representations[95].weights[3] = 0.0f; - representations[95].meanCosines[3] = 0.0f; - representations[95].kappas[3] = 0.0f; - representations[95].normalizations[3] = 0.0f; - - representations[96].K = 3; - representations[96].g = 0.7483464566929133f; - representations[96].weights[0] = 0.3637801026569973f; - representations[96].meanCosines[0] = 0.9638517343301604f; - representations[96].kappas[0] = 28.11849281221908f; - representations[96].normalizations[0] = 4.475197123358596f; - representations[96].weights[1] = 0.4019044800572026f; - representations[96].meanCosines[1] = 0.8106696644633893f; - representations[96].kappas[1] = 5.540161579519249f; - representations[96].normalizations[1] = 0.8817576911146353f; - representations[96].weights[2] = 0.23431541728580002f; - representations[96].meanCosines[2] = 0.2938680432362927f; - representations[96].kappas[2] = 0.937157604192799f; - representations[96].normalizations[2] = 0.17619163714893982f; - representations[96].weights[3] = 0.0f; - representations[96].meanCosines[3] = 0.0f; - representations[96].kappas[3] = 0.0f; - representations[96].normalizations[3] = 0.0f; - - representations[97].K = 3; - representations[97].g = 0.7561417322834645f; - representations[97].weights[0] = 0.3743768742282063f; - representations[97].meanCosines[0] = 0.9654321509327287f; - representations[97].kappas[0] = 29.385253280066383f; - representations[97].normalizations[0] = 4.676808313529897f; - representations[97].weights[1] = 0.3980522577175622f; - representations[97].meanCosines[1] = 0.8147852920835721f; - representations[97].kappas[1] = 5.662895174359178f; - representations[97].normalizations[1] = 0.9012886268604031f; - representations[97].weights[2] = 0.22757086805423143f; - representations[97].meanCosines[2] = 0.2966910234570728f; - representations[97].kappas[2] = 0.947347470721517f; - representations[97].normalizations[2] = 0.17745842680432455f; - representations[97].weights[3] = 0.0f; - representations[97].meanCosines[3] = 0.0f; - representations[97].kappas[3] = 0.0f; - representations[97].normalizations[3] = 0.0f; - - representations[98].K = 3; - representations[98].g = 0.7639370078740157f; - representations[98].weights[0] = 0.38524176513689695f; - representations[98].meanCosines[0] = 0.9669824484448641f; - representations[98].kappas[0] = 30.745511243403147f; - representations[98].normalizations[0] = 4.893300092275056f; - representations[98].weights[1] = 0.39395082537468784f; - representations[98].meanCosines[1] = 0.8188931287879918f; - representations[98].kappas[1] = 5.790709872115165f; - representations[98].normalizations[1] = 0.921628706315985f; - representations[98].weights[2] = 0.22080740948841507f; - representations[98].meanCosines[2] = 0.29953406232822644f; - representations[98].kappas[2] = 0.9576486593632786f; - representations[98].normalizations[2] = 0.1787430116657337f; - representations[98].weights[3] = 0.0f; - representations[98].meanCosines[3] = 0.0f; - representations[98].kappas[3] = 0.0f; - representations[98].normalizations[3] = 0.0f; - - representations[99].K = 3; - representations[99].g = 0.7717322834645669f; - representations[99].weights[0] = 0.3963834354896696f; - representations[99].meanCosines[0] = 0.9685029693213756f; - representations[99].kappas[0] = 32.20952726109539f; - representations[99].normalizations[0] = 5.126305478256488f; - representations[99].weights[1] = 0.389591128435386f; - representations[99].meanCosines[1] = 0.8229956105366834f; - representations[99].kappas[1] = 5.924025346530906f; - representations[99].normalizations[1] = 0.9428446605844728f; - representations[99].weights[2] = 0.21402543607494445f; - representations[99].meanCosines[2] = 0.30239959610284156f; - representations[99].kappas[2] = 0.9680714987483626f; - representations[99].normalizations[2] = 0.1800467850491632f; - representations[99].weights[3] = 0.0f; - representations[99].meanCosines[3] = 0.0f; - representations[99].kappas[3] = 0.0f; - representations[99].normalizations[3] = 0.0f; - - representations[100].K = 3; - representations[100].g = 0.7795275590551181f; - representations[100].weights[0] = 0.40781114817626546f; - representations[100].meanCosines[0] = 0.9699940148344911f; - representations[100].kappas[0] = 33.78906273533941f; - representations[100].normalizations[0] = 5.377696356771425f; - representations[100].weights[1] = 0.384963568809248f; - representations[100].meanCosines[1] = 0.8270952239166515f; - representations[100].kappas[1] = 6.0633086088731885f; - representations[100].normalizations[1] = 0.9650107606665378f; - representations[100].weights[2] = 0.20722528301448653f; - representations[100].meanCosines[2] = 0.3052902696089327f; - representations[100].kappas[2] = 0.9786272634654758f; - representations[100].normalizations[2] = 0.18137127457879043f; - representations[100].weights[3] = 0.0f; - representations[100].meanCosines[3] = 0.0f; - representations[100].kappas[3] = 0.0f; - representations[100].normalizations[3] = 0.0f; - - representations[101].K = 3; - representations[101].g = 0.7873228346456692f; - representations[101].weights[0] = 0.41953483679279924f; - representations[101].meanCosines[0] = 0.9714558448595689f; - representations[101].kappas[0] = 35.49765836096025f; - representations[101].normalizations[0] = 5.649627796334172f; - representations[101].weights[1] = 0.3800579408710988f; - representations[101].meanCosines[1] = 0.8311945147568722f; - representations[101].kappas[1] = 6.209080996730074f; - representations[101].normalizations[1] = 0.9882099294651575f; - representations[101].weights[2] = 0.2004072223361021f; - representations[101].meanCosines[2] = 0.3082089606822717f; - representations[101].kappas[2] = 0.9893282893087417f; - representations[101].normalizations[2] = 0.18271815867924948f; - representations[101].weights[3] = 0.0f; - representations[101].meanCosines[3] = 0.0f; - representations[101].kappas[3] = 0.0f; - representations[101].normalizations[3] = 0.0f; - - representations[102].K = 3; - representations[102].g = 0.7951181102362205f; - representations[102].weights[0] = 0.4315651834971288f; - representations[102].meanCosines[0] = 0.9728886774534552f; - representations[102].kappas[0] = 37.35097594771657f; - representations[102].normalizations[0] = 5.944592451385582f; - representations[102].weights[1] = 0.3748633576315606f; - representations[102].meanCosines[1] = 0.8352960978646506f; - representations[102].kappas[1] = 6.361926458461669f; - representations[102].normalizations[1] = 1.0125350600042866f; - representations[102].weights[2] = 0.1935714588713106f; - representations[102].meanCosines[2] = 0.3111588084871263f; - representations[102].kappas[2] = 1.0001881071793164f; - representations[102].normalizations[2] = 0.18408928574987296f; - representations[102].weights[3] = 0.0f; - representations[102].meanCosines[3] = 0.0f; - representations[102].kappas[3] = 0.0f; - representations[102].normalizations[3] = 0.0f; - - representations[103].K = 3; - representations[103].g = 0.8029133858267716f; - representations[103].weights[0] = 0.44391370756781706f; - representations[103].meanCosines[0] = 0.9742926882438233f; - representations[103].kappas[0] = 39.367220961959f; - representations[103].normalizations[0] = 6.265487811886654f; - representations[103].weights[1] = 0.36936816605135847f; - representations[103].meanCosines[1] = 0.8394026685967423f; - representations[103].kappas[1] = 6.522501446086053f; - representations[103].normalizations[1] = 1.038090589640147f; - representations[103].weights[2] = 0.18671812638082452f; - representations[103].meanCosines[2] = 0.31414324697871443f; - representations[103].kappas[2] = 1.0112216011955533f; - representations[103].normalizations[2] = 0.18548669679179886f; - representations[103].weights[3] = 0.0f; - representations[103].meanCosines[3] = 0.0f; - representations[103].kappas[3] = 0.0f; - representations[103].normalizations[3] = 0.0f; - - representations[104].K = 3; - representations[104].g = 0.8107086614173228f; - representations[104].weights[0] = 0.4565928655077412f; - representations[104].meanCosines[0] = 0.9756680097086392f; - representations[104].kappas[0] = 41.567668857394764f; - representations[104].normalizations[0] = 6.615699971461414f; - representations[104].weights[1] = 0.3635598499248879f; - representations[104].meanCosines[1] = 0.8435170173064288f; - representations[104].kappas[1] = 6.691546828263287f; - representations[104].normalizations[1] = 1.0649943957813093f; - representations[104].weights[2] = 0.17984728456737106f; - representations[104].meanCosines[2] = 0.3171660455034625f; - representations[104].kappas[2] = 1.0224451996197383f; - representations[104].normalizations[2] = 0.18691265266954193f; - representations[104].weights[3] = 0.0f; - representations[104].meanCosines[3] = 0.0f; - representations[104].kappas[3] = 0.0f; - representations[104].normalizations[3] = 0.0f; - - representations[105].K = 3; - representations[105].g = 0.8185039370078739f; - representations[105].weights[0] = 0.4696161649129583f; - representations[105].meanCosines[0] = 0.977014730283103f; - representations[105].kappas[0] = 43.97732584501906f; - representations[105].normalizations[0] = 6.999208792197747f; - representations[105].weights[1] = 0.35742491854950126f; - representations[105].meanCosines[1] = 0.84764204686941f; - representations[105].kappas[1] = 6.869902315309078f; - representations[105].normalizations[1] = 1.093380091409223f; - representations[105].weights[2] = 0.17295891653754053f; - representations[105].meanCosines[2] = 0.32023135742690917f; - representations[105].kappas[2] = 1.0338771035147776f; - representations[105].normalizations[2] = 0.18836966675060354f; - representations[105].weights[3] = 0.0f; - representations[105].meanCosines[3] = 0.0f; - representations[105].kappas[3] = 0.0f; - representations[105].normalizations[3] = 0.0f; - - representations[106].K = 3; - representations[106].g = 0.8262992125984252f; - representations[106].weights[0] = 0.4829982941672016f; - representations[106].meanCosines[0] = 0.9783328932720207f; - representations[106].kappas[0] = 46.62576555511482f; - representations[106].normalizations[0] = 7.420721063540353f; - representations[106].weights[1] = 0.35094877818208203f; - representations[106].meanCosines[1] = 0.8517807946686041f; - representations[106].kappas[1] = 7.058524082784808f; - representations[106].normalizations[1] = 1.1233998296647842f; - representations[106].weights[2] = 0.16605292765071641f; - representations[106].meanCosines[2] = 0.3233437801620528f; - representations[106].kappas[2] = 1.0455375677314898f; - representations[106].normalizations[2] = 0.18986054493140442f; - representations[106].weights[3] = 0.0f; - representations[106].meanCosines[3] = 0.0f; - representations[106].kappas[3] = 0.0f; - representations[106].normalizations[3] = 0.0f; - - representations[107].K = 3; - representations[107].g = 0.8340944881889764f; - representations[107].weights[0] = 0.4967552695533019f; - representations[107].meanCosines[0] = 0.9796224956118234f; - representations[107].kappas[0] = 49.548198396402306f; - representations[107].normalizations[0] = 7.885840696085349f; - representations[107].weights[1] = 0.34411558431336736f; - representations[107].meanCosines[1] = 0.8559364605914935f; - representations[107].kappas[1] = 7.258506499478957f; - representations[107].normalizations[1] = 1.155227761664598f; - representations[107].weights[2] = 0.15912914613333057f; - representations[107].meanCosines[2] = 0.32650842986505385f; - representations[107].kappas[2] = 1.0574492492183072f; - representations[107].normalizations[2] = 0.19138843516693316f; - representations[107].weights[3] = 0.0f; - representations[107].meanCosines[3] = 0.0f; - representations[107].kappas[3] = 0.0f; - representations[107].normalizations[3] = 0.0f; - - representations[108].K = 3; - representations[108].g = 0.8418897637795275f; - representations[108].weights[0] = 0.5109046020998166f; - representations[108].meanCosines[0] = 0.9808834864797452f; - representations[108].kappas[0] = 52.786852197566795f; - representations[108].normalizations[0] = 8.401288457504034f; - representations[108].weights[1] = 0.3369080716212091f; - representations[108].meanCosines[1] = 0.8601124431065127f; - representations[108].kappas[1] = 7.471109181727082f; - representations[108].normalizations[1] = 1.1890643420250768f; - representations[108].weights[2] = 0.15218732627897416f; - representations[108].meanCosines[2] = 0.329731035892612f; - representations[108].kappas[2] = 1.069637645498256f; - representations[108].normalizations[2] = 0.19295688969917166f; - representations[108].weights[3] = 0.0f; - representations[108].meanCosines[3] = 0.0f; - representations[108].kappas[3] = 0.0f; - representations[108].normalizations[3] = 0.0f; - - representations[109].K = 3; - representations[109].g = 0.8496850393700787f; - representations[109].weights[0] = 0.5254626731586894f; - representations[109].meanCosines[0] = 0.9821159342861068f; - representations[109].kappas[0] = 56.39330160029513f; - representations[109].normalizations[0] = 8.975272706959062f; - representations[109].weights[1] = 0.3293094541752853f; - representations[109].meanCosines[1] = 0.8643135954007387f; - representations[109].kappas[1] = 7.69785828048804f; - representations[109].normalizations[1] = 1.2251524488594658f; - representations[109].weights[2] = 0.14522787266602524f; - representations[109].meanCosines[2] = 0.333019161366721f; - representations[109].kappas[2] = 1.0821358440292181f; - representations[109].normalizations[2] = 0.19457048614110656f; - representations[109].weights[3] = 0.0f; - representations[109].meanCosines[3] = 0.0f; - representations[109].kappas[3] = 0.0f; - representations[109].normalizations[3] = 0.0f; - - representations[110].K = 3; - representations[110].g = 0.8574803149606299f; - representations[110].weights[0] = 0.5404523430049603f; - representations[110].meanCosines[0] = 0.98331956425316f; - representations[110].kappas[0] = 60.429586611677735f; - representations[110].normalizations[0] = 9.617667418248331f; - representations[110].weights[1] = 0.3212977300181286f; - representations[110].meanCosines[1] = 0.8685431140960943f; - representations[110].kappas[1] = 7.940423625414496f; - representations[110].normalizations[1] = 1.2637578304420414f; - representations[110].weights[2] = 0.1382499269769111f; - representations[110].meanCosines[2] = 0.3363795356492694f; - representations[110].kappas[2] = 1.094974535419832f; - representations[110].normalizations[2] = 0.19623354919267594f; - representations[110].weights[3] = 0.0f; - representations[110].meanCosines[3] = 0.0f; - representations[110].kappas[3] = 0.0f; - representations[110].normalizations[3] = 0.0f; - - representations[111].K = 3; - representations[111].g = 0.8652755905511811f; - representations[111].weights[0] = 0.5559119561109656f; - representations[111].meanCosines[0] = 0.9844933366024191f; - representations[111].kappas[0] = 64.96899206355937f; - representations[111].normalizations[0] = 10.340136234613592f; - representations[111].weights[1] = 0.31283862434945703f; - representations[111].meanCosines[1] = 0.8727988632471873f; - representations[111].kappas[1] = 8.20040365631985f; - representations[111].normalizations[1] = 1.3051348756250123f; - representations[111].weights[2] = 0.13124941953957747f; - representations[111].meanCosines[2] = 0.339814518724571f; - representations[111].kappas[2] = 1.1081683784152283f; - representations[111].normalizations[2] = 0.19794837195289897f; - representations[111].weights[3] = 0.0f; - representations[111].meanCosines[3] = 0.0f; - representations[111].kappas[3] = 0.0f; - representations[111].normalizations[3] = 0.0f; - - representations[112].K = 3; - representations[112].g = 0.8730708661417322f; - representations[112].weights[0] = 0.5718393884942973f; - representations[112].meanCosines[0] = 0.9856385541741431f; - representations[112].kappas[0] = 70.11289450093315f; - representations[112].normalizations[0] = 11.158813734304077f; - representations[112].weights[1] = 0.3039279013397253f; - representations[112].meanCosines[1] = 0.877097567216021f; - representations[112].kappas[1] = 8.480895648432082f; - representations[112].normalizations[1] = 1.3497765223508311f; - representations[112].weights[2] = 0.12423271016597735f; - representations[112].meanCosines[2] = 0.34334507908236944f; - representations[112].kappas[2] = 1.1218045936162597f; - representations[112].normalizations[2] = 0.1997267555056942f; - representations[112].weights[3] = 0.0f; - representations[112].meanCosines[3] = 0.0f; - representations[112].kappas[3] = 0.0f; - representations[112].normalizations[3] = 0.0f; - - representations[113].K = 3; - representations[113].g = 0.8808661417322834f; - representations[113].weights[0] = 0.5882755569376641f; - representations[113].meanCosines[0] = 0.9867541732199454f; - representations[113].kappas[0] = 75.97889680688574f; - representations[113].normalizations[0] = 12.09241699748489f; - representations[113].weights[1] = 0.29452813547870665f; - representations[113].meanCosines[1] = 0.8814393829516305f; - representations[113].kappas[1] = 8.784435438014446f; - representations[113].normalizations[1] = 1.3980863550011564f; - representations[113].weights[2] = 0.11719630758362938f; - representations[113].meanCosines[2] = 0.34697797664221613f; - representations[113].kappas[2] = 1.1359172624615688f; - representations[113].normalizations[2] = 0.201573696281553f; - representations[113].weights[3] = 0.0f; - representations[113].meanCosines[3] = 0.0f; - representations[113].kappas[3] = 0.0f; - representations[113].normalizations[3] = 0.0f; - - representations[114].K = 3; - representations[114].g = 0.8886614173228347f; - representations[114].weights[0] = 0.6052504230780653f; - representations[114].meanCosines[0] = 0.9878398850719791f; - representations[114].kappas[0] = 82.7208461258252f; - representations[114].normalizations[0] = 13.165431557669141f; - representations[114].weights[1] = 0.28460934660642634f; - representations[114].meanCosines[1] = 0.8858313360968593f; - representations[114].kappas[1] = 9.114532078598165f; - representations[114].normalizations[1] = 1.450622851848577f; - representations[114].weights[2] = 0.11014023031550828f; - representations[114].meanCosines[2] = 0.35072796340726353f; - representations[114].kappas[2] = 1.1505728992115452f; - representations[114].normalizations[2] = 0.20349852757540107f; - representations[114].weights[3] = 0.0f; - representations[114].meanCosines[3] = 0.0f; - representations[114].kappas[3] = 0.0f; - representations[114].normalizations[3] = 0.0f; - - representations[115].K = 3; - representations[115].g = 0.8964566929133858f; - representations[115].weights[0] = 0.6228027995524672f; - representations[115].meanCosines[0] = 0.9888950555229361f; - representations[115].kappas[0] = 90.53608079149387f; - representations[115].normalizations[0] = 14.409264786133447f; - representations[115].weights[1] = 0.2741336567223465f; - representations[115].meanCosines[1] = 0.8902793797177282f; - representations[115].kappas[1] = 9.475314166168351f; - representations[115].normalizations[1] = 1.5080430957712354f; - representations[115].weights[2] = 0.10306354372518628f; - representations[115].meanCosines[2] = 0.35461082756841766f; - representations[115].kappas[2] = 1.1658441284758267f; - representations[115].normalizations[2] = 0.20551152432759512f; - representations[115].weights[3] = 0.0f; - representations[115].meanCosines[3] = 0.0f; - representations[115].kappas[3] = 0.0f; - representations[115].normalizations[3] = 0.0f; - - representations[116].K = 3; - representations[116].g = 0.904251968503937f; - representations[116].weights[0] = 0.6409625400276326f; - representations[116].meanCosines[0] = 0.9899195955960743f; - representations[116].kappas[0] = 99.68975599147025f; - representations[116].normalizations[0] = 15.866117441667381f; - representations[116].weights[1] = 0.2630691381584243f; - representations[116].meanCosines[1] = 0.8947966101812765f; - representations[116].kappas[1] = 9.872432613573858f; - representations[116].normalizations[1] = 1.571246454971746f; - representations[116].weights[2] = 0.095968321813943f; - representations[116].meanCosines[2] = 0.35865262749978183f; - representations[116].kappas[2] = 1.1818467475255494f; - representations[116].normalizations[2] = 0.20762883801820764f; - representations[116].weights[3] = 0.0f; - representations[116].meanCosines[3] = 0.0f; - representations[116].kappas[3] = 0.0f; - representations[116].normalizations[3] = 0.0f; - - representations[117].K = 3; - representations[117].g = 0.9120472440944881f; - representations[117].weights[0] = 0.6597760942835212f; - representations[117].meanCosines[0] = 0.990912757734808f; - representations[117].kappas[0] = 110.53301707231405f; - representations[117].normalizations[0] = 17.59187604191964f; - representations[117].weights[1] = 0.2513693157615257f; - representations[117].meanCosines[1] = 0.8993933442306955f; - representations[117].kappas[1] = 10.312609687465988f; - representations[117].normalizations[1] = 1.6413028097479578f; - representations[117].weights[2] = 0.08885458995495317f; - representations[117].meanCosines[2] = 0.3628812013801927f; - representations[117].kappas[2] = 1.1987075268355516f; - representations[117].normalizations[2] = 0.20986833173806205f; - representations[117].weights[3] = 0.0f; - representations[117].meanCosines[3] = 0.0f; - representations[117].kappas[3] = 0.0f; - representations[117].normalizations[3] = 0.0f; - - representations[118].K = 3; - representations[118].g = 0.9198425196850394f; - representations[118].weights[0] = 0.6792894636829033f; - representations[118].meanCosines[0] = 0.9918739739911012f; - representations[118].kappas[0] = 123.55121730910922f; - representations[118].normalizations[0] = 19.663786959765673f; - representations[118].weights[1] = 0.23898619212136155f; - representations[118].meanCosines[1] = 0.90408570736703f; - representations[118].kappas[1] = 10.804874085633132f; - representations[118].normalizations[1] = 1.719649120922708f; - representations[118].weights[2] = 0.0817243441957352f; - representations[118].meanCosines[2] = 0.3673375775419639f; - representations[118].kappas[2] = 1.2166110601123843f; - representations[118].normalizations[2] = 0.2122558873307257f; - representations[118].weights[3] = 0.0f; - representations[118].meanCosines[3] = 0.0f; - representations[118].kappas[3] = 0.0f; - representations[118].normalizations[3] = 0.0f; - - representations[119].K = 3; - representations[119].g = 0.9276377952755905f; - representations[119].weights[0] = 0.6995522112361258f; - representations[119].meanCosines[0] = 0.9928026697072287f; - representations[119].kappas[0] = 139.4314038120058f; - representations[119].normalizations[0] = 22.191197138922863f; - representations[119].weights[1] = 0.22586650550479143f; - representations[119].meanCosines[1] = 0.9088960661837021f; - representations[119].kappas[1] = 11.361507506541727f; - representations[119].normalizations[1] = 1.8082400808865704f; - representations[119].weights[2] = 0.07458128325908273f; - representations[119].meanCosines[2] = 0.3720816407633235f; - representations[119].kappas[2] = 1.2358257584794836f; - representations[119].normalizations[2] = 0.21482908030767447f; - representations[119].weights[3] = 0.0f; - representations[119].meanCosines[3] = 0.0f; - representations[119].kappas[3] = 0.0f; - representations[119].normalizations[3] = 0.0f; - - representations[120].K = 3; - representations[120].g = 0.9354330708661417f; - representations[120].weights[0] = 0.7206159394099868f; - representations[120].meanCosines[0] = 0.9936983266077104f; - representations[120].kappas[0] = 159.18012629540559f; - representations[120].normalizations[0] = 25.33430394190599f; - representations[120].weights[1] = 0.2119520463912963f; - representations[120].meanCosines[1] = 0.9138572737432618f; - representations[120].kappas[1] = 11.999993458215888f; - representations[120].normalizations[1] = 1.9098582760175666f; - representations[120].weights[2] = 0.06743201419871682f; - representations[120].meanCosines[2] = 0.37720700329635093f; - representations[120].kappas[2] = 1.2567696961188874f; - representations[120].normalizations[2] = 0.2176463521023088f; - representations[120].weights[3] = 0.0f; - representations[120].meanCosines[3] = 0.0f; - representations[120].kappas[3] = 0.0f; - representations[120].normalizations[3] = 0.0f; - - representations[121].K = 3; - representations[121].g = 0.9432283464566928f; - representations[121].weights[0] = 0.7425298903086794f; - representations[121].meanCosines[0] = 0.9945606294046142f; - representations[121].kappas[0] = 184.33799721904487f; - representations[121].normalizations[0] = 29.338303457071046f; - representations[121].weights[1] = 0.19718172827509786f; - representations[121].meanCosines[1] = 0.9190211970423342f; - representations[121].kappas[1] = 12.746832832976239f; - representations[121].normalizations[1] = 2.028721454151434f; - representations[121].weights[2] = 0.06028838141622271f; - representations[121].meanCosines[2] = 0.3828729966523628f; - representations[121].kappas[2] = 1.2801527883158197f; - representations[121].normalizations[2] = 0.22080684477938303f; - representations[121].weights[3] = 0.0f; - representations[121].meanCosines[3] = 0.0f; - representations[121].kappas[3] = 0.0f; - representations[121].normalizations[3] = 0.0f; - - representations[122].K = 3; - representations[122].g = 0.9510236220472441f; - representations[122].weights[0] = 0.7653293103607429f; - representations[122].meanCosines[0] = 0.9953898118117097f; - representations[122].kappas[0] = 217.4051196152159f; - representations[122].normalizations[0] = 34.60109944024639f; - representations[122].weights[1] = 0.18149838112785868f; - representations[122].meanCosines[1] = 0.9244773850283557f; - representations[122].kappas[1] = 13.64592273008513f; - representations[122].normalizations[1] = 2.1718160555461488f; - representations[122].weights[2] = 0.05317230851139854f; - representations[122].meanCosines[2] = 0.3893806024131917f; - representations[122].kappas[2] = 1.3073167675130757f; - representations[122].normalizations[2] = 0.22449796615062265f; - representations[122].weights[3] = 0.0f; - representations[122].meanCosines[3] = 0.0f; - representations[122].kappas[3] = 0.0f; - representations[122].normalizations[3] = 0.0f; - - representations[123].K = 3; - representations[123].g = 0.9588188976377953f; - representations[123].weights[0] = 0.7890052405183582f; - representations[123].meanCosines[0] = 0.9961874879915438f; - representations[123].kappas[0] = 262.7894883431296f; - representations[123].normalizations[0] = 41.82424606239909f; - representations[123].weights[1] = 0.16486806075823146f; - representations[123].meanCosines[1] = 0.9303977710641655f; - representations[123].kappas[1] = 14.779725799317857f; - representations[123].normalizations[1] = 2.352266418504593f; - representations[123].weights[2] = 0.04612669872341031f; - representations[123].meanCosines[2] = 0.3973748382479435f; - representations[123].kappas[2] = 1.3411535562102717f; - representations[123].normalizations[2] = 0.22912451559489155f; - representations[123].weights[3] = 0.0f; - representations[123].meanCosines[3] = 0.0f; - representations[123].kappas[3] = 0.0f; - representations[123].normalizations[3] = 0.0f; - - representations[124].K = 3; - representations[124].g = 0.9666141732283464f; - representations[124].weights[0] = 0.8134132864130297f; - representations[124].meanCosines[0] = 0.9969590951155314f; - representations[124].kappas[0] = 329.34568100402697f; - representations[124].normalizations[0] = 52.41699311775743f; - representations[124].weights[1] = 0.14734309576502963f; - representations[124].meanCosines[1] = 0.9371602294155938f; - representations[124].kappas[1] = 16.334429702579303f; - representations[124].normalizations[1] = 2.599705229752591f; - representations[124].weights[2] = 0.03924361782194063f; - representations[124].meanCosines[2] = 0.4084766247518925f; - representations[124].kappas[2] = 1.38903995811237f; - representations[124].normalizations[2] = 0.2357246896803882f; - representations[124].weights[3] = 0.0f; - representations[124].meanCosines[3] = 0.0f; - representations[124].kappas[3] = 0.0f; - representations[124].normalizations[3] = 0.0f; - - representations[125].K = 3; - representations[125].g = 0.9744094488188976f; - representations[125].weights[0] = 0.8380377885238703f; - representations[125].meanCosines[0] = 0.9977192495345887f; - representations[125].kappas[0] = 438.9493224499256f; - representations[125].normalizations[0] = 69.86095443474393f; - representations[125].weights[1] = 0.12922359501050967f; - representations[125].meanCosines[1] = 0.9456890221956583f; - representations[125].kappas[1] = 18.84421609415959f; - representations[125].normalizations[1] = 2.999150140077348f; - representations[125].weights[2] = 0.03273861646562f; - representations[125].meanCosines[2] = 0.42761937604381417f; - representations[125].kappas[2] = 1.4742417480145642f; - representations[125].normalizations[2] = 0.24761249545923705f; - representations[125].weights[3] = 0.0f; - representations[125].meanCosines[3] = 0.0f; - representations[125].kappas[3] = 0.0f; - representations[125].normalizations[3] = 0.0f; - - representations[126].K = 3; - representations[126].g = 0.9822047244094488f; - representations[126].weights[0] = 0.86110354278221f; - representations[126].meanCosines[0] = 0.9985077831939306f; - representations[126].kappas[0] = 670.6420411084238f; - representations[126].normalizations[0] = 106.73599588764372f; - representations[126].weights[1] = 0.11170062456703932f; - representations[126].meanCosines[1] = 0.958498099808663f; - representations[126].kappas[1] = 24.543185034997688f; - representations[126].normalizations[1] = 3.906169217538914f; - representations[126].weights[2] = 0.027195832650750658f; - representations[126].meanCosines[2] = 0.47512959398520177f; - representations[126].kappas[2] = 1.7024552564942006f; - representations[126].normalizations[2] = 0.28026159880811696f; - representations[126].weights[3] = 0.0f; - representations[126].meanCosines[3] = 0.0f; - representations[126].kappas[3] = 0.0f; - representations[126].normalizations[3] = 0.0f; - - representations[127].K = 3; - representations[127].g = 0.99f; - representations[127].weights[0] = 0.868073622158317f; - representations[127].meanCosines[0] = 0.9994691382373244f; - representations[127].kappas[0] = 1884.2289065113011f; - representations[127].normalizations[0] = 299.88434438791035f; - representations[127].weights[1] = 0.10584342660588578f; - representations[127].meanCosines[1] = 0.9844441544134342f; - representations[127].kappas[1] = 64.76504041838344f; - representations[127].normalizations[1] = 10.307676322132117f; - representations[127].weights[2] = 0.026082951235797305f; - representations[127].meanCosines[2] = 0.7491038510925567f; - representations[127].kappas[2] = 4.163095340893173f; - representations[127].normalizations[2] = 0.6627376458781823f; - representations[127].weights[3] = 0.0f; - representations[127].meanCosines[3] = 0.0f; - representations[127].kappas[3] = 0.0f; - representations[127].normalizations[3] = 0.0f; - } -} \ No newline at end of file +namespace openpgl +{ + +std::array VMMSingleLobeHenyeyGreensteinOracle::representations; +float VMMSingleLobeHenyeyGreensteinOracle::minMeanCosine; //{0.f}; +float VMMSingleLobeHenyeyGreensteinOracle::maxMeanCosine; //{0.99f}; +int VMMSingleLobeHenyeyGreensteinOracle::numRepresentations; + +void VMMSingleLobeHenyeyGreensteinOracle::init() +{ + /* VMM representations of the single lobe HG phase function. + The 3-lobe VMMs are fitted using a least squares optimization framework + as described by S. Herholz: + - "Path Guiding in Production" + - - "Volumetric Zero-variance Based Path Guiding" (Chapter 11.5) + */ + + minMeanCosine = 0.0f; + maxMeanCosine = 0.99f; + numRepresentations = 128; + + representations[0].K = 3; + representations[0].g = 0.0f; + representations[0].weights[0] = 0.01688512612073299f; + representations[0].meanCosines[0] = 0.0f; + representations[0].kappas[0] = 0.0f; + representations[0].normalizations[0] = 0.07957747154594767f; + representations[0].weights[1] = 0.34940739552081895f; + representations[0].meanCosines[1] = 0.0f; + representations[0].kappas[1] = 0.0f; + representations[0].normalizations[1] = 0.07957747154594767f; + representations[0].weights[2] = 0.6337074783584481f; + representations[0].meanCosines[2] = 0.0f; + representations[0].kappas[2] = 0.0f; + representations[0].normalizations[2] = 0.07957747154594767f; + representations[0].weights[3] = 0.0f; + representations[0].meanCosines[3] = 0.0f; + representations[0].kappas[3] = 0.0f; + representations[0].normalizations[3] = 0.0f; + + representations[1].K = 3; + representations[1].g = 0.007795275590551181f; + representations[1].weights[0] = 0.01688512612254555f; + representations[1].meanCosines[0] = 0.03588398182493312f; + representations[1].kappas[0] = 0.10774447737138962f; + representations[1].normalizations[0] = 0.08845920147738665f; + representations[1].weights[1] = 0.34940739552017397f; + representations[1].meanCosines[1] = 0.014362686373439479f; + representations[1].kappas[1] = 0.043093986007026464f; + representations[1].normalizations[1] = 0.08305603677895068f; + representations[1].weights[2] = 0.6337074783572806f; + representations[1].meanCosines[2] = 0.003425584458792068f; + representations[1].kappas[2] = 0.010276833773244303f; + representations[1].normalizations[2] = 0.08039807745351672f; + representations[1].weights[3] = 0.0f; + representations[1].meanCosines[3] = 0.0f; + representations[1].kappas[3] = 0.0f; + representations[1].normalizations[3] = 0.0f; + + representations[2].K = 3; + representations[2].g = 0.015590551181102362f; + representations[2].weights[0] = 0.01688437903886321f; + representations[2].meanCosines[0] = 0.07165186574299764f; + representations[2].kappas[0] = 0.21569511380458395f; + representations[2].normalizations[0] = 0.09797223006527885f; + representations[2].weights[1] = 0.34940741896923394f; + representations[2].meanCosines[1] = 0.028726867492049023f; + representations[2].kappas[1] = 0.08622805434824445f; + representations[2].normalizations[1] = 0.08663641125148722f; + representations[2].weights[2] = 0.6337082019919029f; + representations[2].meanCosines[2] = 0.006852355953716443f; + representations[2].kappas[2] = 0.02055771139312781f; + representations[2].normalizations[2] = 0.08122461225390147f; + representations[2].weights[3] = 0.0f; + representations[2].meanCosines[3] = 0.0f; + representations[2].kappas[3] = 0.0f; + representations[2].normalizations[3] = 0.0f; + + representations[3].K = 3; + representations[3].g = 0.02338582677165354f; + representations[3].weights[0] = 0.01688251644451822f; + representations[3].meanCosines[0] = 0.10719000956269134f; + representations[3].kappas[0] = 0.3240618203310573f; + representations[3].normalizations[0] = 0.10813182001250154f; + representations[3].weights[1] = 0.34940749421528944f; + representations[3].meanCosines[1] = 0.043094103168718915f; + representations[3].kappas[1] = 0.12944266757431747f; + representations[3].normalizations[1] = 0.09032214696897492f; + representations[3].weights[2] = 0.6337099893401924f; + representations[3].meanCosines[2] = 0.010281511556840308f; + representations[3].kappas[2] = 0.03084670860680498f; + representations[3].normalizations[2] = 0.0820574128582956f; + representations[3].weights[3] = 0.0f; + representations[3].meanCosines[3] = 0.0f; + representations[3].kappas[3] = 0.0f; + representations[3].normalizations[3] = 0.0f; + + representations[4].K = 3; + representations[4].g = 0.031181102362204723f; + representations[4].weights[0] = 0.016879170271827615f; + representations[4].meanCosines[0] = 0.14238854747740515f; + representations[4].kappas[0] = 0.43305883676258095f; + representations[4].normalizations[0] = 0.1189527446874129f; + representations[4].weights[1] = 0.3494076744789957f; + representations[4].meanCosines[1] = 0.05746593132255443f; + representations[4].kappas[1] = 0.17277859481192268f; + representations[4].normalizations[1] = 0.09411704443372311f; + representations[4].weights[2] = 0.6337131552491766f; + representations[4].meanCosines[2] = 0.013714266562698281f; + representations[4].kappas[2] = 0.04114795944743138f; + representations[4].normalizations[2] = 0.08289682936908468f; + representations[4].weights[3] = 0.0f; + representations[4].meanCosines[3] = 0.0f; + representations[4].kappas[3] = 0.0f; + representations[4].normalizations[3] = 0.0f; + + representations[5].K = 3; + representations[5].g = 0.0389763779527559f; + representations[5].weights[0] = 0.01688212081880487f; + representations[5].meanCosines[0] = 0.17712402739360683f; + representations[5].kappas[0] = 0.5428458438663006f; + representations[5].normalizations[0] = 0.13044306812363982f; + representations[5].weights[1] = 0.3494073468644722f; + representations[5].meanCosines[1] = 0.07184106550223494f; + representations[5].kappas[1] = 0.21626860707980294f; + representations[5].normalizations[1] = 0.09802439780640325f; + representations[5].weights[2] = 0.6337105323167227f; + representations[5].meanCosines[2] = 0.017151877226518623f; + representations[5].kappas[2] = 0.05146572636419975f; + representations[5].normalizations[2] = 0.08374323102430331f; + representations[5].weights[3] = 0.0f; + representations[5].meanCosines[3] = 0.0f; + representations[5].kappas[3] = 0.0f; + representations[5].normalizations[3] = 0.0f; + + representations[6].K = 3; + representations[6].g = 0.04677165354330708f; + representations[6].weights[0] = 0.016911780064021775f; + representations[6].meanCosines[0] = 0.2112319819771247f; + representations[6].kappas[0] = 0.6534261871553656f; + representations[6].normalizations[0] = 0.1425912900682853f; + representations[6].weights[1] = 0.349406832800622f; + representations[6].meanCosines[1] = 0.08621065078660167f; + representations[6].kappas[1] = 0.25992303076611534f; + representations[6].normalizations[1] = 0.10204555335170774f; + representations[6].weights[2] = 0.6336813871353562f; + representations[6].meanCosines[2] = 0.020595569081659132f; + representations[6].kappas[2] = 0.061804187012100144f; + representations[6].normalizations[2] = 0.08459698890239761f; + representations[6].weights[3] = 0.0f; + representations[6].meanCosines[3] = 0.0f; + representations[6].kappas[3] = 0.0f; + representations[6].normalizations[3] = 0.0f; + + representations[7].K = 3; + representations[7].g = 0.054566929133858265f; + representations[7].weights[0] = 0.01698431443686933f; + representations[7].meanCosines[0] = 0.24453864844476111f; + representations[7].kappas[0] = 0.764722497664732f; + representations[7].normalizations[0] = 0.1553715185073856f; + representations[7].weights[1] = 0.34940688968611067f; + representations[7].meanCosines[1] = 0.10056215754823958f; + representations[7].kappas[1] = 0.3037411707083553f; + representations[7].normalizations[1] = 0.10618074302045714f; + representations[7].weights[2] = 0.6336087958770199f; + representations[7].meanCosines[2] = 0.024046530657178572f; + representations[7].kappas[2] = 0.07216741718299197f; + representations[7].normalizations[2] = 0.08545847429102746f; + representations[7].weights[3] = 0.0f; + representations[7].meanCosines[3] = 0.0f; + representations[7].kappas[3] = 0.0f; + representations[7].normalizations[3] = 0.0f; + + representations[8].K = 3; + representations[8].g = 0.06236220472440945f; + representations[8].weights[0] = 0.017178062978008293f; + representations[8].meanCosines[0] = 0.2766513150830249f; + representations[8].kappas[0] = 0.8758112176782963f; + representations[8].normalizations[0] = 0.1686489715158632f; + representations[8].weights[1] = 0.34940624966149436f; + representations[8].meanCosines[1] = 0.11484549630313552f; + representations[8].kappas[1] = 0.34760648721076526f; + representations[8].normalizations[1] = 0.11041871452215614f; + representations[8].weights[2] = 0.6334156873604974f; + representations[8].meanCosines[2] = 0.027505759421599836f; + representations[8].kappas[2] = 0.08255892966571578f; + representations[8].normalizations[2] = 0.08632801972235461f; + representations[8].weights[3] = 0.0f; + representations[8].meanCosines[3] = 0.0f; + representations[8].kappas[3] = 0.0f; + representations[8].normalizations[3] = 0.0f; + + representations[9].K = 3; + representations[9].g = 0.07015748031496062f; + representations[9].weights[0] = 0.017371006808467492f; + representations[9].meanCosines[0] = 0.30782730487102705f; + representations[9].kappas[0] = 0.9879265175144101f; + representations[9].normalizations[0] = 0.18254148705094658f; + representations[9].weights[1] = 0.34928506189089986f; + representations[9].meanCosines[1] = 0.129131147364166f; + representations[9].kappas[1] = 0.3917729556957539f; + representations[9].normalizations[1] = 0.11478405680653793f; + representations[9].weights[2] = 0.6333439313006328f; + representations[9].meanCosines[2] = 0.030983196797823992f; + representations[9].kappas[2] = 0.09300913271687389f; + representations[9].normalizations[2] = 0.08720823784227144f; + representations[9].weights[3] = 0.0f; + representations[9].meanCosines[3] = 0.0f; + representations[9].kappas[3] = 0.0f; + representations[9].normalizations[3] = 0.0f; + + representations[10].K = 3; + representations[10].g = 0.0779527559055118f; + representations[10].weights[0] = 0.017584981738709496f; + representations[10].meanCosines[0] = 0.33794984524349103f; + representations[10].kappas[0] = 1.1009972551142273f; + representations[10].normalizations[0] = 0.1970156107265375f; + representations[10].weights[1] = 0.349155889550176f; + representations[10].meanCosines[1] = 0.1433912150580251f; + representations[10].kappas[1] = 0.4361939745876183f; + representations[10].normalizations[1] = 0.11927274711513454f; + representations[10].weights[2] = 0.6332591287111146f; + representations[10].meanCosines[2] = 0.034474217471298856f; + representations[10].kappas[2] = 0.10350469317865921f; + representations[10].normalizations[2] = 0.08809808759230493f; + representations[10].weights[3] = 0.0f; + representations[10].meanCosines[3] = 0.0f; + representations[10].kappas[3] = 0.0f; + representations[10].normalizations[3] = 0.0f; + + representations[11].K = 3; + representations[11].g = 0.08574803149606298f; + representations[11].weights[0] = 0.017809322999872215f; + representations[11].meanCosines[0] = 0.3670064050195432f; + representations[11].kappas[0] = 1.2152757532992868f; + representations[11].normalizations[0] = 0.21207747870839172f; + representations[11].weights[1] = 0.34897319658417403f; + representations[11].meanCosines[1] = 0.1576390635881601f; + representations[11].kappas[1] = 0.4809515295890107f; + representations[11].normalizations[1] = 0.12389359991430093f; + representations[11].weights[2] = 0.6332174804159536f; + representations[11].meanCosines[2] = 0.037984321862009805f; + representations[11].kappas[2] = 0.11406273217887339f; + representations[11].normalizations[2] = 0.08899910551739097f; + representations[11].weights[3] = 0.0f; + representations[11].meanCosines[3] = 0.0f; + representations[11].kappas[3] = 0.0f; + representations[11].normalizations[3] = 0.0f; + + representations[12].K = 3; + representations[12].g = 0.09354330708661417f; + representations[12].weights[0] = 0.01826527507863583f; + representations[12].meanCosines[0] = 0.3942271824887726f; + representations[12].kappas[0] = 1.3277678345776889f; + representations[12].normalizations[0] = 0.2272905167499025f; + representations[12].weights[1] = 0.3497662056173708f; + representations[12].meanCosines[1] = 0.17148377049971156f; + representations[12].kappas[1] = 0.5248424174065418f; + representations[12].normalizations[1] = 0.12851914003354303f; + representations[12].weights[2] = 0.6319685193039934f; + representations[12].meanCosines[2] = 0.04141831747731281f; + representations[12].kappas[2] = 0.12439730097148566f; + representations[12].normalizations[2] = 0.08988675023967237f; + representations[12].weights[3] = 0.0f; + representations[12].meanCosines[3] = 0.0f; + representations[12].kappas[3] = 0.0f; + representations[12].normalizations[3] = 0.0f; + + representations[13].K = 3; + representations[13].g = 0.10133858267716535f; + representations[13].weights[0] = 0.01876291998771093f; + representations[13].meanCosines[0] = 0.42020042532807644f; + representations[13].kappas[0] = 1.4408083884538716f; + representations[13].normalizations[0] = 0.24292636119361116f; + representations[13].weights[1] = 0.35061939871117465f; + representations[13].meanCosines[1] = 0.18520867376560435f; + representations[13].kappas[1] = 0.5687835020385287f; + representations[13].normalizations[1] = 0.13324175902122393f; + representations[13].weights[2] = 0.6306176813011145f; + representations[13].meanCosines[2] = 0.04484781190877385f; + representations[13].kappas[2] = 0.13472420647644337f; + representations[13].normalizations[2] = 0.09077936160410964f; + representations[13].weights[3] = 0.0f; + representations[13].meanCosines[3] = 0.0f; + representations[13].kappas[3] = 0.0f; + representations[13].normalizations[3] = 0.0f; + + representations[14].K = 3; + representations[14].g = 0.10913385826771653f; + representations[14].weights[0] = 0.019306961289135425f; + representations[14].meanCosines[0] = 0.44492057851788697f; + representations[14].kappas[0] = 1.5543850149507152f; + representations[14].normalizations[0] = 0.25895176916401214f; + representations[14].weights[1] = 0.35154945670839527f; + representations[14].meanCosines[1] = 0.19879827489247553f; + representations[14].kappas[1] = 0.6127546945467943f; + representations[14].normalizations[1] = 0.1380578383493104f; + representations[14].weights[2] = 0.6291435820024692f; + representations[14].meanCosines[2] = 0.0482705272418375f; + representations[14].kappas[2] = 0.14503705196651462f; + representations[14].normalizations[2] = 0.0916763629745512f; + representations[14].weights[3] = 0.0f; + representations[14].meanCosines[3] = 0.0f; + representations[14].kappas[3] = 0.0f; + representations[14].normalizations[3] = 0.0f; + + representations[15].K = 3; + representations[15].g = 0.11692913385826771f; + representations[15].weights[0] = 0.01989845510400388f; + representations[15].meanCosines[0] = 0.4684068719141528f; + representations[15].kappas[0] = 1.6685346475413192f; + representations[15].normalizations[0] = 0.2753414373527367f; + representations[15].weights[1] = 0.35255534710456443f; + representations[15].meanCosines[1] = 0.21224370805221723f; + representations[15].kappas[1] = 0.6567552077580507f; + representations[15].normalizations[1] = 0.1429656644773955f; + representations[15].weights[2] = 0.6275461977914317f; + representations[15].meanCosines[2] = 0.051685704986140286f; + representations[15].kappas[2] = 0.155334002273931f; + representations[15].normalizations[2] = 0.09257756389054712f; + representations[15].weights[3] = 0.0f; + representations[15].meanCosines[3] = 0.0f; + representations[15].kappas[3] = 0.0f; + representations[15].normalizations[3] = 0.0f; + + representations[16].K = 3; + representations[16].g = 0.1247244094488189f; + representations[16].weights[0] = 0.020535354184989436f; + representations[16].meanCosines[0] = 0.49069955616971095f; + representations[16].kappas[0] = 1.7833511441174834f; + representations[16].normalizations[0] = 0.292080078167316f; + representations[16].weights[1] = 0.353622508898923f; + representations[16].meanCosines[1] = 0.22554330566749264f; + representations[16].kappas[1] = 0.7008064498892924f; + representations[16].normalizations[1] = 0.14796596420736946f; + representations[16].weights[2] = 0.6258421369160876f; + representations[16].meanCosines[2] = 0.055094314525624195f; + representations[16].kappas[2] = 0.16561842664237564f; + representations[16].normalizations[2] = 0.09348322926408528f; + representations[16].weights[3] = 0.0f; + representations[16].meanCosines[3] = 0.0f; + representations[16].kappas[3] = 0.0f; + representations[16].normalizations[3] = 0.0f; + + representations[17].K = 3; + representations[17].g = 0.13251968503937006f; + representations[17].weights[0] = 0.021218949410057832f; + representations[17].meanCosines[0] = 0.5118356933074103f; + representations[17].kappas[0] = 1.8988787667383773f; + representations[17].normalizations[0] = 0.30914733250021437f; + representations[17].weights[1] = 0.3547509744956134f; + representations[17].meanCosines[1] = 0.23868968600098744f; + representations[17].kappas[1] = 0.7449098193050739f; + representations[17].normalizations[1] = 0.15305721242482156f; + representations[17].weights[2] = 0.6240300760943289f; + representations[17].meanCosines[2] = 0.05849576027428436f; + representations[17].kappas[2] = 0.1758889715094559f; + representations[17].normalizations[2] = 0.09439321119322305f; + representations[17].weights[3] = 0.0f; + representations[17].meanCosines[3] = 0.0f; + representations[17].kappas[3] = 0.0f; + representations[17].normalizations[3] = 0.0f; + + representations[18].K = 3; + representations[18].g = 0.14031496062992124f; + representations[18].weights[0] = 0.021949824475763605f; + representations[18].meanCosines[0] = 0.5318607735970473f; + representations[18].kappas[0] = 2.0151765919095097f; + representations[18].normalizations[0] = 0.32652706617217647f; + representations[18].weights[1] = 0.355937499042096f; + representations[18].meanCosines[1] = 0.2516775828350221f; + representations[18].kappas[1] = 0.7890721855355327f; + representations[18].normalizations[1] = 0.15823845763667177f; + representations[18].weights[2] = 0.6221126764821404f; + representations[18].meanCosines[2] = 0.06188987023100114f; + representations[18].kappas[2] = 0.1861455542022604f; + representations[18].normalizations[2] = 0.095307472119436f; + representations[18].weights[3] = 0.0f; + representations[18].meanCosines[3] = 0.0f; + representations[18].kappas[3] = 0.0f; + representations[18].normalizations[3] = 0.0f; + + representations[19].K = 3; + representations[19].g = 0.14811023622047242f; + representations[19].weights[0] = 0.02272913643627242f; + representations[19].meanCosines[0] = 0.5508226752301884f; + representations[19].kappas[0] = 2.1322958845677973f; + representations[19].normalizations[0] = 0.34420411555954816f; + representations[19].weights[1] = 0.35718094247354754f; + representations[19].meanCosines[1] = 0.2645011566729811f; + representations[19].kappas[1] = 0.83329691124312f; + representations[19].normalizations[1] = 0.16350830114410747f; + representations[19].weights[2] = 0.6200899210901799f; + representations[19].meanCosines[2] = 0.06527619808965157f; + representations[19].kappas[2] = 0.19638725613213096f; + representations[19].normalizations[2] = 0.09622589876681735f; + representations[19].weights[3] = 0.0f; + representations[19].meanCosines[3] = 0.0f; + representations[19].kappas[3] = 0.0f; + representations[19].normalizations[3] = 0.0f; + + representations[20].K = 3; + representations[20].g = 0.1559055118110236f; + representations[20].weights[0] = 0.02355816434063645f; + representations[20].meanCosines[0] = 0.5687717007838606f; + representations[20].kappas[0] = 2.2502875905814577f; + representations[20].normalizations[0] = 0.3621653738462567f; + representations[20].weights[1] = 0.35848028814660143f; + representations[20].meanCosines[1] = 0.27715490333500015f; + representations[20].kappas[1] = 0.877586789540549f; + representations[20].normalizations[1] = 0.1688652288634378f; + representations[20].weights[2] = 0.6179615475127621f; + representations[20].meanCosines[2] = 0.06865425253449127f; + representations[20].kappas[2] = 0.20661301330820872f; + representations[20].normalizations[2] = 0.09714836239583771f; + representations[20].weights[3] = 0.0f; + representations[20].meanCosines[3] = 0.0f; + representations[20].kappas[3] = 0.0f; + representations[20].normalizations[3] = 0.0f; + + representations[21].K = 3; + representations[21].g = 0.1637007874015748f; + representations[21].weights[0] = 0.024437905025832977f; + representations[21].meanCosines[0] = 0.5857605240246847f; + representations[21].kappas[0] = 2.369210817881718f; + representations[21].normalizations[0] = 0.3804010540382946f; + representations[21].weights[1] = 0.3598331385814581f; + representations[21].meanCosines[1] = 0.2896345928505576f; + representations[21].kappas[1] = 0.9219473564693016f; + representations[21].normalizations[1] = 0.17430802225670775f; + representations[21].weights[2] = 0.615728956392709f; + representations[21].meanCosines[2] = 0.0720237515533397f; + representations[21].kappas[2] = 0.21682238610695004f; + representations[21].normalizations[2] = 0.0980747884961609f; + representations[21].weights[3] = 0.0f; + representations[21].meanCosines[3] = 0.0f; + representations[21].kappas[3] = 0.0f; + representations[21].normalizations[3] = 0.0f; + + representations[22].K = 3; + representations[22].g = 0.17149606299212597f; + representations[22].weights[0] = 0.02536961631311807f; + representations[22].meanCosines[0] = 0.6018414369673392f; + representations[22].kappas[0] = 2.4891221301227326f; + representations[22].normalizations[0] = 0.3989029937166436f; + representations[22].weights[1] = 0.36123782439484414f; + representations[22].meanCosines[1] = 0.3019360372422726f; + representations[22].kappas[1] = 0.9663826317493759f; + representations[22].normalizations[1] = 0.1798352546930349f; + representations[22].weights[2] = 0.6133925592920377f; + representations[22].meanCosines[2] = 0.07538429370718021f; + representations[22].kappas[2] = 0.227014564370858f; + representations[22].normalizations[2] = 0.09900506739744325f; + representations[22].weights[3] = 0.0f; + representations[22].meanCosines[3] = 0.0f; + representations[22].kappas[3] = 0.0f; + representations[22].normalizations[3] = 0.0f; + + representations[23].K = 3; + representations[23].g = 0.17929133858267715f; + representations[23].weights[0] = 0.026354489815300336f; + representations[23].meanCosines[0] = 0.6170665107763216f; + representations[23].kappas[0] = 2.6100823069456927f; + representations[23].normalizations[0] = 0.41766558456512115f; + representations[23].weights[1] = 0.3626921762477047f; + representations[23].meanCosines[1] = 0.3140558294414811f; + representations[23].kappas[1] = 1.01089774821742f; + representations[23].normalizations[1] = 0.18544561804238008f; + representations[23].weights[2] = 0.6109533339369949f; + representations[23].meanCosines[2] = 0.07873555976785689f; + representations[23].kappas[2] = 0.23718897773507175f; + representations[23].normalizations[2] = 0.09993910949879477f; + representations[23].weights[3] = 0.0f; + representations[23].meanCosines[3] = 0.0f; + representations[23].kappas[3] = 0.0f; + representations[23].normalizations[3] = 0.0f; + + representations[24].K = 3; + representations[24].g = 0.18708661417322833f; + representations[24].weights[0] = 0.027393813480758946f; + representations[24].meanCosines[0] = 0.6314864653894078f; + representations[24].kappas[0] = 2.732153035175755f; + representations[24].normalizations[0] = 0.43668514425861027f; + representations[24].weights[1] = 0.36419412912481675f; + representations[24].meanCosines[1] = 0.3259909557058004f; + representations[24].kappas[1] = 1.0554976150974884f; + representations[24].normalizations[1] = 0.19113776574149305f; + representations[24].weights[2] = 0.6084120573944244f; + representations[24].meanCosines[2] = 0.0820772098121622f; + representations[24].kappas[2] = 0.24734498362097554f; + representations[24].normalizations[2] = 0.10087681703497244f; + representations[24].weights[3] = 0.0f; + representations[24].meanCosines[3] = 0.0f; + representations[24].kappas[3] = 0.0f; + representations[24].normalizations[3] = 0.0f; + + representations[25].K = 3; + representations[25].g = 0.19488188976377951f; + representations[25].weights[0] = 0.02848894330183947f; + representations[25].meanCosines[0] = 0.6451502887946322f; + representations[25].kappas[0] = 2.855397531861139f; + representations[25].normalizations[0] = 0.4559598770309509f; + representations[25].weights[1] = 0.3657416121853952f; + representations[25].meanCosines[1] = 0.3377388443459699f; + representations[25].kappas[1] = 1.1001871225871562f; + representations[25].normalizations[1] = 0.19691034293610063f; + representations[25].weights[2] = 0.6057694445127654f; + representations[25].meanCosines[2] = 0.08540889854051824f; + representations[25].kappas[2] = 0.2574819131914485f; + representations[25].normalizations[2] = 0.10181808818723857f; + representations[25].weights[3] = 0.0f; + representations[25].meanCosines[3] = 0.0f; + representations[25].kappas[3] = 0.0f; + representations[25].normalizations[3] = 0.0f; + + representations[26].K = 3; + representations[26].g = 0.2026771653543307f; + representations[26].weights[0] = 0.029641232684561578f; + representations[26].meanCosines[0] = 0.6581050795977398f; + representations[26].kappas[0] = 2.979882270484645f; + representations[26].normalizations[0] = 0.47549000441135625f; + representations[26].weights[1] = 0.36733232742198196f; + representations[26].meanCosines[1] = 0.34929751692855454f; + representations[26].kappas[1] = 1.1449717768941352f; + representations[26].normalizations[1] = 0.20276207496603466f; + representations[26].weights[2] = 0.6030264398934564f; + representations[26].meanCosines[2] = 0.0887303226670217f; + representations[26].kappas[2] = 0.267599215342648f; + representations[26].normalizations[2] = 0.10276283052115276f; + representations[26].weights[3] = 0.0f; + representations[26].meanCosines[3] = 0.0f; + representations[26].kappas[3] = 0.0f; + representations[26].normalizations[3] = 0.0f; + + representations[27].K = 3; + representations[27].g = 0.21047244094488188f; + representations[27].weights[0] = 0.03085210788273518f; + representations[27].meanCosines[0] = 0.6703956245596104f; + representations[27].kappas[0] = 3.1056753595617264f; + representations[27].normalizations[0] = 0.4952773717297844f; + representations[27].weights[1] = 0.3689640002885473f; + representations[27].meanCosines[1] = 0.3606653920204467f; + representations[27].kappas[1] = 1.1898570305342318f; + representations[27].normalizations[1] = 0.20869168777485336f; + representations[27].weights[2] = 0.6001838918287176f; + representations[27].meanCosines[2] = 0.09204116986781731f; + representations[27].kappas[2] = 0.27769630133596485f; + representations[27].normalizations[2] = 0.10371094668741296f; + representations[27].weights[3] = 0.0f; + representations[27].meanCosines[3] = 0.0f; + representations[27].kappas[3] = 0.0f; + representations[27].normalizations[3] = 0.0f; + + representations[28].K = 3; + representations[28].g = 0.21826771653543306f; + representations[28].weights[0] = 0.03212300887954878f; + representations[28].meanCosines[0] = 0.6820644132559194f; + representations[28].kappas[0] = 3.2328480493359963f; + representations[28].normalizations[0] = 0.5153255463626063f; + representations[28].weights[1] = 0.3706342080413193f; + representations[28].meanCosines[1] = 0.371841402019988f; + representations[28].kappas[1] = 1.2348488131529798f; + representations[28].normalizations[1] = 0.21469798321963257f; + representations[28].weights[2] = 0.597242783079132f; + representations[28].meanCosines[2] = 0.095341157518617f; + representations[28].kappas[2] = 0.28777266268317936f; + representations[28].normalizations[2] = 0.10466234550768412f; + representations[28].weights[3] = 0.0f; + representations[28].meanCosines[3] = 0.0f; + representations[28].kappas[3] = 0.0f; + representations[28].normalizations[3] = 0.0f; + + representations[29].K = 3; + representations[29].g = 0.22606299212598424f; + representations[29].weights[0] = 0.03345544514793685f; + representations[29].meanCosines[0] = 0.6931514474568911f; + representations[29].kappas[0] = 3.3614734966515782f; + representations[29].normalizations[0] = 0.5356394908307532f; + representations[29].weights[1] = 0.37234054521898624f; + representations[29].meanCosines[1] = 0.3828248418078445f; + representations[29].kappas[1] = 1.2799530194570734f; + representations[29].normalizations[1] = 0.22077977707335444f; + representations[29].weights[2] = 0.5942040096330768f; + representations[29].meanCosines[2] = 0.09862999422597651f; + representations[29].kappas[2] = 0.29782775373429926f; + representations[29].normalizations[2] = 0.10561693102809376f; + representations[29].weights[3] = 0.0f; + representations[29].meanCosines[3] = 0.0f; + representations[29].kappas[3] = 0.0f; + representations[29].normalizations[3] = 0.0f; + + representations[30].K = 3; + representations[30].g = 0.23385826771653542f; + representations[30].weights[0] = 0.0348509218277539f; + representations[30].meanCosines[0] = 0.703694400485129f; + representations[30].kappas[0] = 3.491628707455712f; + representations[30].normalizations[0] = 0.5562257439894829f; + representations[30].weights[1] = 0.3740804275025195f; + representations[30].meanCosines[1] = 0.39361551569233905f; + representations[30].kappas[1] = 1.325176201006904f; + representations[30].normalizations[1] = 0.22693599717230062f; + representations[30].weights[2] = 0.5910686506697266f; + representations[30].meanCosines[2] = 0.10190742993352812f; + representations[30].kappas[2] = 0.3078611447237137f; + representations[30].normalizations[2] = 0.10657461709345743f; + representations[30].weights[3] = 0.0f; + representations[30].meanCosines[3] = 0.0f; + representations[30].kappas[3] = 0.0f; + representations[30].normalizations[3] = 0.0f; + + representations[31].K = 3; + representations[31].g = 0.2416535433070866f; + representations[31].weights[0] = 0.0363110174513472f; + representations[31].meanCosines[0] = 0.7137284878918613f; + representations[31].kappas[0] = 3.6233927446497733f; + representations[31].normalizations[0] = 0.5770920215898871f; + representations[31].weights[1] = 0.3758513101926688f; + representations[31].meanCosines[1] = 0.40421353232046997f; + representations[31].kappas[1] = 1.370524826949544f; + representations[31].normalizations[1] = 0.23316558894026745f; + representations[31].weights[2] = 0.5878376723559839f; + representations[31].meanCosines[2] = 0.10517320052735003f; + representations[31].kappas[2] = 0.3178723524295186f; + representations[31].normalizations[2] = 0.10753531137309834f; + representations[31].weights[3] = 0.0f; + representations[31].meanCosines[3] = 0.0f; + representations[31].kappas[3] = 0.0f; + representations[31].normalizations[3] = 0.0f; + + representations[32].K = 3; + representations[32].g = 0.2494488188976378f; + representations[32].weights[0] = 0.03783733033391697f; + representations[32].meanCosines[0] = 0.7232866503493903f; + representations[32].kappas[0] = 3.7568481915190235f; + representations[32].normalizations[0] = 0.5982473403971204f; + representations[32].weights[1] = 0.377650546588742f; + representations[32].meanCosines[1] = 0.4146194044606831f; + representations[32].kappas[1] = 1.416005797772609f; + representations[32].normalizations[1] = 0.23946758934791837f; + representations[32].weights[2] = 0.5845121230773409f; + representations[32].meanCosines[2] = 0.10842706502773718f; + representations[32].kappas[2] = 0.32786095389288733f; + representations[32].normalizations[2] = 0.10849892624542931f; + representations[32].weights[3] = 0.0f; + representations[32].meanCosines[3] = 0.0f; + representations[32].kappas[3] = 0.0f; + representations[32].normalizations[3] = 0.0f; + + representations[33].K = 3; + representations[33].g = 0.25724409448818897f; + representations[33].weights[0] = 0.039431478172527346f; + representations[33].meanCosines[0] = 0.7323996378740554f; + representations[33].kappas[0] = 3.892081342390479f; + representations[33].normalizations[0] = 0.6197019514445599f; + representations[33].weights[1] = 0.37947540366321675f; + representations[33].meanCosines[1] = 0.42483402082021005f; + representations[33].kappas[1] = 1.4616264505862715f; + representations[33].normalizations[1] = 0.2458411328184177f; + representations[33].weights[2] = 0.5810931181642559f; + representations[33].meanCosines[2] = 0.11166880441579947f; + representations[33].kappas[2] = 0.33782658307981484f; + representations[33].normalizations[2] = 0.10946537864825562f; + representations[33].weights[3] = 0.0f; + representations[33].meanCosines[3] = 0.0f; + representations[33].kappas[3] = 0.0f; + representations[33].normalizations[3] = 0.0f; + + representations[34].K = 3; + representations[34].g = 0.2650393700787401f; + representations[34].weights[0] = 0.04109511413829938f; + representations[34].meanCosines[0] = 0.7410960812812006f; + representations[34].kappas[0] = 4.029181949359587f; + representations[34].normalizations[0] = 0.6414672123825825f; + representations[34].weights[1] = 0.3813231066295435f; + representations[34].meanCosines[1] = 0.43485858368855124f; + representations[34].kappas[1] = 1.5073944073067256f; + representations[34].normalizations[1] = 0.2522854344127896f; + representations[34].weights[2] = 0.5775817792321571f; + representations[34].meanCosines[2] = 0.1148982096999848f; + representations[34].kappas[2] = 0.3477688944033129f; + representations[34].normalizations[2] = 0.11043458667809568f; + representations[34].weights[3] = 0.0f; + representations[34].meanCosines[3] = 0.0f; + representations[34].kappas[3] = 0.0f; + representations[34].normalizations[3] = 0.0f; + + representations[35].K = 3; + representations[35].g = 0.27283464566929133f; + representations[35].weights[0] = 0.04282992980429418f; + representations[35].meanCosines[0] = 0.7494026016728395f; + representations[35].kappas[0] = 4.1682433077297265f; + representations[35].normalizations[0] = 0.6635555227768634f; + representations[35].weights[1] = 0.3831908473467149f; + representations[35].meanCosines[1] = 0.4446945773353679f; + representations[35].kappas[1] = 1.5533175460677648f; + representations[35].normalizations[1] = 0.258799789085319f; + representations[35].weights[2] = 0.5739792228489909f; + representations[35].meanCosines[2] = 0.11811507896449913f; + representations[35].kappas[2] = 0.35768755366547783f; + representations[35].normalizations[2] = 0.11140646877150544f; + representations[35].weights[3] = 0.0f; + representations[35].meanCosines[3] = 0.0f; + representations[35].kappas[3] = 0.0f; + representations[35].normalizations[3] = 0.0f; + + representations[36].K = 3; + representations[36].g = 0.2806299212598425f; + representations[36].weights[0] = 0.04463760356304057f; + representations[36].meanCosines[0] = 0.7573440065673147f; + representations[36].kappas[0] = 4.309363834506902f; + representations[36].normalizations[0] = 0.685980505664905f; + representations[36].weights[1] = 0.3850756892916237f; + representations[36].meanCosines[1] = 0.4543438495874592f; + representations[36].kappas[1] = 1.5994045135644068f; + representations[36].normalizations[1] = 0.2653836478950735f; + representations[36].weights[2] = 0.5702867071453358f; + representations[36].meanCosines[2] = 0.12131925204563446f; + representations[36].kappas[2] = 0.3675823452228001f; + representations[36].normalizations[2] = 0.1123809543338033f; + representations[36].weights[3] = 0.0f; + representations[36].meanCosines[3] = 0.0f; + representations[36].kappas[3] = 0.0f; + representations[36].normalizations[3] = 0.0f; + + representations[37].K = 3; + representations[37].g = 0.2884251968503937f; + representations[37].weights[0] = 0.04651992132996143f; + representations[37].meanCosines[0] = 0.7649432204882097f; + representations[37].kappas[0] = 4.452644004080665f; + representations[37].normalizations[0] = 0.7087564597863664f; + representations[37].weights[1] = 0.3869748043395022f; + representations[37].meanCosines[1] = 0.46380833521269565f; + representations[37].kappas[1] = 1.6456635357182618f; + representations[37].normalizations[1] = 0.2720364511995345f; + representations[37].weights[2] = 0.5665052743305363f; + representations[37].meanCosines[2] = 0.12451052633673292f; + representations[37].kappas[2] = 0.3774529122318213f; + representations[37].normalizations[2] = 0.11335795827691708f; + representations[37].weights[3] = 0.0f; + representations[37].meanCosines[3] = 0.0f; + representations[37].kappas[3] = 0.0f; + representations[37].normalizations[3] = 0.0f; + + representations[38].K = 3; + representations[38].g = 0.29622047244094485f; + representations[38].weights[0] = 0.04847852891549287f; + representations[38].meanCosines[0] = 0.7722217618748662f; + representations[38].kappas[0] = 4.5981933220302285f; + representations[38].normalizations[0] = 0.7318994148658073f; + representations[38].weights[1] = 0.388885024846989f; + representations[38].meanCosines[1] = 0.473090536062836f; + representations[38].kappas[1] = 1.6921048843771227f; + representations[38].normalizations[1] = 0.27875798554095554f; + representations[38].weights[2] = 0.5626364462375181f; + representations[38].meanCosines[2] = 0.12768882647952162f; + representations[38].kappas[2] = 0.38729928159477f; + representations[38].normalizations[2] = 0.11433743303630248f; + representations[38].weights[3] = 0.0f; + representations[38].meanCosines[3] = 0.0f; + representations[38].kappas[3] = 0.0f; + representations[38].normalizations[3] = 0.0f; + + representations[39].K = 3; + representations[39].g = 0.30401574803149606f; + representations[39].weights[0] = 0.050515288560540404f; + representations[39].meanCosines[0] = 0.7791993428816343f; + representations[39].kappas[0] = 4.746120804250555f; + representations[39].normalizations[0] = 0.7554255718985057f; + representations[39].weights[1] = 0.39080348821235833f; + representations[39].meanCosines[1] = 0.4821927734544212f; + representations[39].kappas[1] = 1.7387373336802003f; + representations[39].normalizations[1] = 0.28554787556787525f; + representations[39].weights[2] = 0.5586812232271012f; + representations[39].meanCosines[2] = 0.13085395797040394f; + representations[39].kappas[2] = 0.39712110186372734f; + representations[39].normalizations[2] = 0.11531929316013426f; + representations[39].weights[3] = 0.0f; + representations[39].meanCosines[3] = 0.0f; + representations[39].kappas[3] = 0.0f; + representations[39].normalizations[3] = 0.0f; + + representations[40].K = 3; + representations[40].g = 0.3118110236220472f; + representations[40].weights[0] = 0.052631938361106065f; + representations[40].meanCosines[0] = 0.785894454230334f; + representations[40].kappas[0] = 4.896544587693031f; + representations[40].normalizations[0] = 0.7793527912550628f; + representations[40].weights[1] = 0.3927270435107326f; + representations[40].meanCosines[1] = 0.4911178490442006f; + representations[40].kappas[1] = 1.7855715658402957f; + representations[40].normalizations[1] = 0.2924060777270106f; + representations[40].weights[2] = 0.5546410181281614f; + representations[40].meanCosines[2] = 0.13400584044657948f; + representations[40].kappas[2] = 0.406918365828317f; + representations[40].normalizations[2] = 0.1163034871611057f; + representations[40].weights[3] = 0.0f; + representations[40].meanCosines[3] = 0.0f; + representations[40].kappas[3] = 0.0f; + representations[40].normalizations[3] = 0.0f; + + representations[41].K = 3; + representations[41].g = 0.3196062992125984f; + representations[41].weights[0] = 0.054830320932235194f; + representations[41].meanCosines[0] = 0.7923241563653624f; + representations[41].kappas[0] = 5.049585889496475f; + representations[41].normalizations[0] = 0.8036995978580225f; + representations[41].weights[1] = 0.39465264154304214f; + representations[41].meanCosines[1] = 0.49986856925941164f; + representations[41].kappas[1] = 1.8326178990052264f; + representations[41].normalizations[1] = 0.299332552386369f; + representations[41].weights[2] = 0.5505170375247227f; + representations[41].meanCosines[2] = 0.13714435057395352f; + representations[41].kappas[2] = 0.4166909238221657f; + representations[41].normalizations[2] = 0.11728994912473324f; + representations[41].weights[3] = 0.0f; + representations[41].meanCosines[3] = 0.0f; + representations[41].kappas[3] = 0.0f; + representations[41].normalizations[3] = 0.0f; + + representations[42].K = 3; + representations[42].g = 0.3274015748031496f; + representations[42].weights[0] = 0.05711223605872792f; + representations[42].meanCosines[0] = 0.7985043630899611f; + representations[42].kappas[0] = 5.205373425292967f; + representations[42].normalizations[0] = 0.828485854647965f; + representations[42].weights[1] = 0.39657710712907207f; + representations[42].meanCosines[1] = 0.5084480072544973f; + representations[42].kappas[1] = 1.8798877748028617f; + representations[42].normalizations[1] = 0.30632748244974595f; + representations[42].weights[2] = 0.5463106568122f; + representations[42].meanCosines[2] = 0.14026942121314215f; + representations[42].kappas[2] = 0.4264387921091299f; + representations[42].normalizations[2] = 0.11827862972883287f; + representations[42].weights[3] = 0.0f; + representations[42].meanCosines[3] = 0.0f; + representations[42].kappas[3] = 0.0f; + representations[42].normalizations[3] = 0.0f; + + representations[43].K = 3; + representations[43].g = 0.3351968503937008f; + representations[43].weights[0] = 0.05947949976675226f; + representations[43].meanCosines[0] = 0.8044498524567503f; + representations[43].kappas[0] = 5.3640421044192195f; + representations[43].normalizations[0] = 0.8537325301915992f; + representations[43].weights[1] = 0.39849724129514225f; + representations[43].meanCosines[1] = 0.516859365291507f; + representations[43].kappas[1] = 1.9273931827012034f; + representations[43].normalizations[1] = 0.31339119081328726f; + representations[43].weights[2] = 0.5420232589381055f; + representations[43].meanCosines[2] = 0.14338100028624415f; + representations[43].kappas[2] = 0.4361620257500823f; + representations[43].normalizations[2] = 0.11926948366904784f; + representations[43].weights[3] = 0.0f; + representations[43].meanCosines[3] = 0.0f; + representations[43].kappas[3] = 0.0f; + representations[43].normalizations[3] = 0.0f; + + representations[44].K = 3; + representations[44].g = 0.34299212598425194f; + representations[44].weights[0] = 0.061934017335778434f; + representations[44].meanCosines[0] = 0.8101742785481437f; + representations[44].kappas[0] = 5.525731270151455f; + representations[44].normalizations[0] = 0.8794613975566535f; + representations[44].weights[1] = 0.400409908304721f; + representations[44].meanCosines[1] = 0.5251058303099392f; + representations[44].kappas[1] = 1.9751459448430044f; + representations[44].normalizations[1] = 0.32052403397373247f; + representations[44].weights[2] = 0.5376560743595005f; + representations[44].meanCosines[2] = 0.14647900283272577f; + representations[44].kappas[2] = 0.4458605687980155f; + representations[44].normalizations[2] = 0.12026245438736198f; + representations[44].weights[3] = 0.0f; + representations[44].meanCosines[3] = 0.0f; + representations[44].kappas[3] = 0.0f; + representations[44].normalizations[3] = 0.0f; + + representations[45].K = 3; + representations[45].g = 0.35078740157480315f; + representations[45].weights[0] = 0.06447760472630311f; + representations[45].meanCosines[0] = 0.8156904376058959f; + representations[45].kappas[0] = 5.6905902250879805f; + representations[45].normalizations[0] = 0.9056958957694585f; + representations[45].weights[1] = 0.40231181608214067f; + representations[45].meanCosines[1] = 0.533190870036375f; + representations[45].kappas[1] = 2.0231595316319937f; + representations[45].normalizations[1] = 0.3277266730567593f; + representations[45].weights[2] = 0.5332105791915562f; + representations[45].meanCosines[2] = 0.14956342791040378f; + representations[45].kappas[2] = 0.4555346203324962f; + representations[45].normalizations[2] = 0.1212575115536747f; + representations[45].weights[3] = 0.0f; + representations[45].meanCosines[3] = 0.0f; + representations[45].kappas[3] = 0.0f; + representations[45].normalizations[3] = 0.0f; + + representations[46].K = 3; + representations[46].g = 0.3585826771653543f; + representations[46].weights[0] = 0.06711202650241141f; + representations[46].meanCosines[0] = 0.8210102816127492f; + representations[46].kappas[0] = 5.858777649296523f; + representations[46].normalizations[0] = 0.9324610224429561f; + representations[46].weights[1] = 0.4041995962417163f; + representations[46].meanCosines[1] = 0.5411181321395668f; + representations[46].kappas[1] = 2.071448705643941f; + representations[46].normalizations[1] = 0.335000023620412f; + representations[46].weights[2] = 0.5286883772558724f; + representations[46].meanCosines[2] = 0.15263433078191485f; + representations[46].kappas[2] = 0.4651845494691381f; + representations[46].normalizations[2] = 0.12225464287484415f; + representations[46].weights[3] = 0.0f; + representations[46].meanCosines[3] = 0.0f; + representations[46].kappas[3] = 0.0f; + representations[46].normalizations[3] = 0.0f; + + representations[47].K = 3; + representations[47].g = 0.3663779527559055f; + representations[47].weights[0] = 0.06983934101319342f; + representations[47].meanCosines[0] = 0.8261446758646345f; + representations[47].kappas[0] = 6.030451916295631f; + representations[47].normalizations[0] = 0.9597817802216335f; + representations[47].weights[1] = 0.40607015469631597f; + representations[47].meanCosines[1] = 0.5488908666357898f; + representations[47].kappas[1] = 2.120026074834621f; + representations[47].normalizations[1] = 0.3423447352950037f; + representations[47].weights[2] = 0.5240905042904906f; + representations[47].meanCosines[2] = 0.1556916023453696f; + representations[47].kappas[2] = 0.47481020201532553f; + representations[47].normalizations[2] = 0.12325378236504182f; + representations[47].weights[3] = 0.0f; + representations[47].meanCosines[3] = 0.0f; + representations[47].kappas[3] = 0.0f; + representations[47].normalizations[3] = 0.0f; + + representations[48].K = 3; + representations[48].g = 0.37417322834645667f; + representations[48].weights[0] = 0.07266134359728532f; + representations[48].meanCosines[0] = 0.8311039776930013f; + representations[48].kappas[0] = 6.20578789794099f; + representations[48].normalizations[0] = 0.9876858407915654f; + representations[48].weights[1] = 0.40792008616982384f; + representations[48].meanCosines[1] = 0.5565128318769808f; + representations[48].kappas[1] = 2.1689077268327046f; + representations[48].normalizations[1] = 0.3497620402640429f; + representations[48].weights[2] = 0.5194185702328908f; + representations[48].meanCosines[2] = 0.158735326448921f; + representations[48].kappas[2] = 0.4844120237797777f; + representations[48].normalizations[2] = 0.1242549265117551f; + representations[48].weights[3] = 0.0f; + representations[48].meanCosines[3] = 0.0f; + representations[48].kappas[3] = 0.0f; + representations[48].normalizations[3] = 0.0f; + + representations[49].K = 3; + representations[49].g = 0.3819685039370079f; + representations[49].weights[0] = 0.07557993630147046f; + representations[49].meanCosines[0] = 0.8358977483762517f; + representations[49].kappas[0] = 6.384966707199992f; + representations[49].normalizations[0] = 1.0162019040631736f; + representations[49].weights[1] = 0.40974607087036374f; + representations[49].meanCosines[1] = 0.5639876672029343f; + representations[49].kappas[1] = 2.2181095428841404f; + representations[49].normalizations[1] = 0.35725319828108354f; + representations[49].weights[2] = 0.5146739928281657f; + representations[49].meanCosines[2] = 0.16176554199961418f; + representations[49].kappas[2] = 0.49399031392292975f; + representations[49].normalizations[2] = 0.1252580573066742f; + representations[49].weights[3] = 0.0f; + representations[49].meanCosines[3] = 0.0f; + representations[49].kappas[3] = 0.0f; + representations[49].normalizations[3] = 0.0f; + + representations[50].K = 3; + representations[50].g = 0.38976377952755903f; + representations[50].weights[0] = 0.07859703707682453f; + representations[50].meanCosines[0] = 0.8405348935900007f; + representations[50].kappas[0] = 6.568178944104258f; + representations[50].normalizations[0] = 1.0453602077318829f; + representations[50].weights[1] = 0.4115447755011663f; + representations[50].meanCosines[1] = 0.5713190337485659f; + representations[50].kappas[1] = 2.2676481499650887f; + representations[50].normalizations[1] = 0.36481963932118755f; + representations[50].weights[2] = 0.5098581874220092f; + representations[50].meanCosines[2] = 0.1647823017041069f; + representations[50].kappas[2] = 0.5035454098977901f; + representations[50].normalizations[2] = 0.1262631614013433f; + representations[50].weights[3] = 0.0f; + representations[50].meanCosines[3] = 0.0f; + representations[50].kappas[3] = 0.0f; + representations[50].normalizations[3] = 0.0f; + + representations[51].K = 3; + representations[51].g = 0.39755905511811024f; + representations[51].weights[0] = 0.08171458128636552f; + representations[51].meanCosines[0] = 0.8450237123238858f; + representations[51].kappas[0] = 6.755625297772691f; + representations[51].normalizations[0] = 1.0751926173713249f; + representations[51].weights[1] = 0.41331285366521353f; + representations[51].meanCosines[1] = 0.5785106025878821f; + representations[51].kappas[1] = 2.317540949797567f; + representations[51].normalizations[1] = 0.3724629673385169f; + representations[51].weights[2] = 0.504972565048421f; + representations[51].meanCosines[2] = 0.16778567162512953f; + representations[51].kappas[2] = 0.5130776865929203f; + representations[51].normalizations[2] = 0.1272702301037747f; + representations[51].weights[3] = 0.0f; + representations[51].meanCosines[3] = 0.0f; + representations[51].kappas[3] = 0.0f; + representations[51].normalizations[3] = 0.0f; + + representations[52].K = 3; + representations[52].g = 0.4053543307086614f; + representations[52].weights[0] = 0.08493448605433432f; + representations[52].meanCosines[0] = 0.8493719674172462f; + representations[52].kappas[0] = 6.947518350251926f; + representations[52].normalizations[0] = 1.1057329088681573f; + representations[52].weights[1] = 0.4150469228659922f; + representations[52].meanCosines[1] = 0.58556609571726f; + representations[52].kappas[1] = 2.367806523563953f; + representations[52].normalizations[1] = 0.3801850217003517f; + representations[52].weights[2] = 0.5000185910796735f; + representations[52].meanCosines[2] = 0.1707757528202662f; + representations[52].kappas[2] = 0.5225876257851102f; + representations[52].normalizations[2] = 0.12827926684695073f; + representations[52].weights[3] = 0.0f; + representations[52].meanCosines[3] = 0.0f; + representations[52].kappas[3] = 0.0f; + representations[52].normalizations[3] = 0.0f; + + representations[53].K = 3; + representations[53].g = 0.4131496062992126f; + representations[53].weights[0] = 0.08825869500909991f; + representations[53].meanCosines[0] = 0.8535868936983303f; + representations[53].kappas[0] = 7.144082003779275f; + representations[53].normalizations[0] = 1.1370166735101817f; + representations[53].weights[1] = 0.4167435990709438f; + representations[53].meanCosines[1] = 0.5924892115715676f; + representations[53].kappas[1] = 2.418464235702139f; + representations[53].normalizations[1] = 0.38798781588098935f; + representations[53].weights[2] = 0.49499770591995634f; + representations[53].meanCosines[2] = 0.17375265446037172f; + representations[53].kappas[2] = 0.5320757316832715f; + representations[53].normalizations[2] = 0.12929027840892207f; + representations[53].weights[3] = 0.0f; + representations[53].meanCosines[3] = 0.0f; + representations[53].kappas[3] = 0.0f; + representations[53].normalizations[3] = 0.0f; + + representations[54].K = 3; + representations[54].g = 0.42094488188976376f; + representations[54].weights[0] = 0.09168916522716564f; + representations[54].meanCosines[0] = 0.8576752472049249f; + representations[54].kappas[0] = 7.345552722466723f; + representations[54].normalizations[0] = 1.1690815125785594f; + representations[54].weights[1] = 0.4183994860545349f; + representations[54].meanCosines[1] = 0.5992836376054463f; + representations[54].kappas[1] = 2.4695344222622806f; + representations[54].normalizations[1] = 0.3958735653601526f; + representations[54].weights[2] = 0.48991134871829956f; + representations[54].meanCosines[2] = 0.17671650241051653f; + representations[54].kappas[2] = 0.541542558806905f; + representations[54].normalizations[2] = 0.13030327794671623f; + representations[54].weights[3] = 0.0f; + representations[54].meanCosines[3] = 0.0f; + representations[54].kappas[3] = 0.0f; + representations[54].normalizations[3] = 0.0f; + + representations[55].K = 3; + representations[55].g = 0.42874015748031497f; + representations[55].weights[0] = 0.09522786839368456f; + representations[55].meanCosines[0] = 0.8616433403817125f; + representations[55].kappas[0] = 7.552180422573271f; + representations[55].normalizations[0] = 1.2019671766214413f; + representations[55].weights[1] = 0.42001117566983376f; + representations[55].meanCosines[1] = 0.6059530427287675f; + representations[55].kappas[1] = 2.5210384425501737f; + representations[55].normalizations[1] = 0.40384469461842903f; + representations[55].weights[2] = 0.48476095593648155f; + representations[55].meanCosines[2] = 0.17966743925929668f; + representations[55].kappas[2] = 0.5509887128325508f; + representations[55].normalizations[2] = 0.13131828519299638f; + representations[55].weights[3] = 0.0f; + representations[55].meanCosines[3] = 0.0f; + representations[55].kappas[3] = 0.0f; + representations[55].normalizations[3] = 0.0f; + + representations[56].K = 3; + representations[56].g = 0.4365354330708661f; + representations[56].weights[0] = 0.0988767934663242f; + representations[56].meanCosines[0] = 0.8654970737530904f; + representations[56].kappas[0] = 7.764229399563398f; + representations[56].normalizations[0] = 1.2357157110806771f; + representations[56].weights[1] = 0.42157524842882677f; + representations[56].meanCosines[1] = 0.612501068934138f; + representations[56].kappas[1] = 2.5729987214001024f; + representations[56].normalizations[1] = 0.4119038426292747f; + representations[56].weights[2] = 0.47954795810484907f; + representations[56].meanCosines[2] = 0.18260562362373325f; + representations[56].kappas[2] = 0.5604148491400338f; + representations[56].normalizations[2] = 0.1323353264040619f; + representations[56].weights[3] = 0.0f; + representations[56].meanCosines[3] = 0.0f; + representations[56].kappas[3] = 0.0f; + representations[56].normalizations[3] = 0.0f; + + representations[57].K = 3; + representations[57].g = 0.44433070866141733f; + representations[57].weights[0] = 0.10263796004725238f; + representations[57].meanCosines[0] = 0.8692419595769955f; + representations[57].kappas[0] = 7.981979001500163f; + representations[57].normalizations[0] = 1.270371561952546f; + representations[57].weights[1] = 0.42308827723445225f; + representations[57].meanCosines[1] = 0.6189313112296096f; + representations[57].kappas[1] = 2.6254386902453777f; + representations[57].normalizations[1] = 0.4200538525478618f; + representations[57].weights[2] = 0.47427376271829536f; + representations[57].meanCosines[2] = 0.18553122367844202f; + representations[57].kappas[2] = 0.5698216527617949f; + representations[57].normalizations[2] = 0.1333544322829776f; + representations[57].weights[3] = 0.0f; + representations[57].meanCosines[3] = 0.0f; + representations[57].kappas[3] = 0.0f; + representations[57].normalizations[3] = 0.0f; + + representations[58].K = 3; + representations[58].g = 0.4521259842519685f; + representations[58].weights[0] = 0.10651340265267141f; + representations[58].meanCosines[0] = 0.8728831598504667f; + representations[58].kappas[0] = 8.20572532527276f; + representations[58].normalizations[0] = 1.3059818445660667f; + representations[58].weights[1] = 0.4245468183339547f; + representations[58].meanCosines[1] = 0.6252473352033313f; + representations[58].kappas[1] = 2.6783830265653674f; + representations[58].normalizations[1] = 0.42829780768018394f; + representations[58].weights[2] = 0.4689397790133738f; + representations[58].meanCosines[2] = 0.18844442736311248f; + representations[58].kappas[2] = 0.5792098718805595f; + representations[58].normalizations[2] = 0.13437564168445362f; + representations[58].weights[3] = 0.0f; + representations[58].meanCosines[3] = 0.0f; + representations[58].kappas[3] = 0.0f; + representations[58].normalizations[3] = 0.0f; + + representations[59].K = 3; + representations[59].g = 0.4599212598425197f; + representations[59].weights[0] = 0.11050517555935604f; + representations[59].meanCosines[0] = 0.8764255095007417f; + representations[59].kappas[0] = 8.435782379970613f; + representations[59].normalizations[0] = 1.342596527819977f; + representations[59].weights[1] = 0.42594741240052664f; + representations[59].meanCosines[1] = 0.6314526684925892f; + representations[59].kappas[1] = 2.7318576950764704f; + representations[59].normalizations[1] = 0.436639036804549f; + representations[59].weights[2] = 0.4635474120401174f; + representations[59].meanCosines[2] = 0.1913454408889863f; + representations[59].kappas[2] = 0.5885803139592967f; + representations[59].normalizations[2] = 0.13539900131670243f; + representations[59].weights[3] = 0.0f; + representations[59].meanCosines[3] = 0.0f; + representations[59].kappas[3] = 0.0f; + representations[59].normalizations[3] = 0.0f; + + representations[60].K = 3; + representations[60].g = 0.46771653543307085f; + representations[60].weights[0] = 0.11461533860200686f; + representations[60].meanCosines[0] = 0.8798735470937176f; + representations[60].kappas[0] = 8.672483998747186f; + representations[60].normalizations[0] = 1.3802687377565923f; + representations[60].weights[1] = 0.42728658030803607f; + representations[60].meanCosines[1] = 0.6375508149620032f; + representations[60].kappas[1] = 2.7858901874628623f; + representations[60].normalizations[1] = 0.4450811504792057f; + representations[60].weights[2] = 0.45809808108995725f; + representations[60].meanCosines[2] = 0.19423449766964776f; + representations[60].kappas[2] = 0.5979338756232817f; + representations[60].normalizations[2] = 0.13642456913873516f; + representations[60].weights[3] = 0.0f; + representations[60].meanCosines[3] = 0.0f; + representations[60].kappas[3] = 0.0f; + representations[60].normalizations[3] = 0.0f; + + representations[61].K = 3; + representations[61].g = 0.47551181102362206f; + representations[61].weights[0] = 0.11884599637104817f; + representations[61].meanCosines[0] = 0.8832315179423937f; + representations[61].kappas[0] = 8.916184139359721f; + representations[61].normalizations[0] = 1.419054804853077f; + representations[61].weights[1] = 0.4285608327734269f; + representations[61].meanCosines[1] = 0.6435452084762158f; + representations[61].kappas[1] = 2.8405092323844556f; + representations[61].normalizations[1] = 0.4536279946281f; + representations[61].weights[2] = 0.4525931708555248f; + representations[61].meanCosines[2] = 0.19711183827311177f; + representations[61].kappas[2] = 0.6072714788289457f; + representations[61].normalizations[2] = 0.1374524074966876f; + representations[61].weights[3] = 0.0f; + representations[61].meanCosines[3] = 0.0f; + representations[61].kappas[3] = 0.0f; + representations[61].normalizations[3] = 0.0f; + + representations[62].K = 3; + representations[62].g = 0.4833070866141732f; + representations[62].weights[0] = 0.12319928766759637f; + representations[62].meanCosines[0] = 0.8865034015121176f; + representations[62].kappas[0] = 9.16725893612397f; + representations[62].normalizations[0] = 1.4590145901905027f; + representations[62].weights[1] = 0.42976666301618144f; + representations[62].meanCosines[1] = 0.6494392269329624f; + representations[62].kappas[1] = 2.8957450141747496f; + representations[62].normalizations[1] = 0.46228368338595593f; + representations[62].weights[2] = 0.44703404931622226f; + representations[62].meanCosines[2] = 0.19997771817476762f; + representations[62].kappas[2] = 0.616594096682104f; + representations[62].normalizations[2] = 0.13848258601896915f; + representations[62].weights[3] = 0.0f; + representations[62].meanCosines[3] = 0.0f; + representations[62].kappas[3] = 0.0f; + representations[62].normalizations[3] = 0.0f; + + representations[63].K = 3; + representations[63].g = 0.4911023622047244f; + representations[63].weights[0] = 0.12767711326081116f; + representations[63].meanCosines[0] = 0.8896930424203258f; + representations[63].kappas[0] = 9.426117857395496f; + representations[63].normalizations[0] = 1.500213260915139f; + representations[63].weights[1] = 0.4309005122013021f; + representations[63].meanCosines[1] = 0.6552364769534045f; + representations[63].kappas[1] = 2.9516320648387557f; + representations[63].normalizations[1] = 0.471053051906239f; + representations[63].weights[2] = 0.44142237453788674f; + representations[63].meanCosines[2] = 0.20283255209471382f; + representations[63].kappas[2] = 0.6259032255561982f; + representations[63].normalizations[2] = 0.13951523417822578f; + representations[63].weights[3] = 0.0f; + representations[63].meanCosines[3] = 0.0f; + representations[63].kappas[3] = 0.0f; + representations[63].normalizations[3] = 0.0f; + + representations[64].K = 3; + representations[64].g = 0.4988976377952756f; + representations[64].weights[0] = 0.13228217893070182f; + representations[64].meanCosines[0] = 0.8928037371351293f; + representations[64].kappas[0] = 9.693170363545615f; + representations[64].normalizations[0] = 1.5427159834637596f; + representations[64].weights[1] = 0.43195889896389156f; + representations[64].meanCosines[1] = 0.6609397021872523f; + representations[64].kappas[1] = 3.0081987975922257f; + representations[64].normalizations[1] = 0.47994001241960793f; + representations[64].weights[2] = 0.43575892210540673f; + representations[64].meanCosines[2] = 0.20567636859603608f; + representations[64].kappas[2] = 0.6351991067898674f; + representations[64].normalizations[2] = 0.14055034398422908f; + representations[64].weights[3] = 0.0f; + representations[64].meanCosines[3] = 0.0f; + representations[64].kappas[3] = 0.0f; + representations[64].normalizations[3] = 0.0f; + + representations[65].K = 3; + representations[65].g = 0.5066929133858268f; + representations[65].weights[0] = 0.13701645780490154f; + representations[65].meanCosines[0] = 0.8958388925416747f; + representations[65].kappas[0] = 9.968880275772742f; + representations[65].normalizations[0] = 1.5865965764607521f; + representations[65].weights[1] = 0.43293821041468983f; + representations[65].meanCosines[1] = 0.6665524055023117f; + representations[65].kappas[1] = 3.0654832705645223f; + representations[65].normalizations[1] = 0.4889500266604984f; + representations[65].weights[2] = 0.4300453317804087f; + representations[65].meanCosines[2] = 0.20850962101611986f; + representations[65].kappas[2] = 0.6444833721001508f; + representations[65].normalizations[2] = 0.14158806355836523f; + representations[65].weights[3] = 0.0f; + representations[65].meanCosines[3] = 0.0f; + representations[65].kappas[3] = 0.0f; + representations[65].normalizations[3] = 0.0f; + + representations[66].K = 3; + representations[66].g = 0.5144881889763779f; + representations[66].weights[0] = 0.14188167518350953f; + representations[66].meanCosines[0] = 0.8988018020497218f; + representations[66].kappas[0] = 10.253752777050046f; + representations[66].normalizations[0] = 1.6319354417346774f; + representations[66].weights[1] = 0.4338348440662771f; + representations[66].meanCosines[1] = 0.672078283990385f; + representations[66].kappas[1] = 3.123528477106368f; + representations[66].normalizations[1] = 0.498089369724428f; + representations[66].weights[2] = 0.42428348075021344f; + representations[66].meanCosines[2] = 0.21133292088157304f; + representations[66].kappas[2] = 0.6537581843157421f; + representations[66].normalizations[2] = 0.14262860345015743f; + representations[66].weights[3] = 0.0f; + representations[66].meanCosines[3] = 0.0f; + representations[66].kappas[3] = 0.0f; + representations[66].normalizations[3] = 0.0f; + + representations[67].K = 3; + representations[67].g = 0.5222834645669291f; + representations[67].weights[0] = 0.14688190532912504f; + representations[67].meanCosines[0] = 0.9016947510325678f; + representations[67].kappas[0] = 10.548244803107089f; + representations[67].normalizations[0] = 1.6788053025137655f; + representations[67].weights[1] = 0.4346451786272443f; + representations[67].meanCosines[1] = 0.6775187639861546f; + representations[67].kappas[1] = 3.18235586208853f; + representations[67].normalizations[1] = 0.5073609548705329f; + representations[67].weights[2] = 0.41847291604363074f; + representations[67].meanCosines[2] = 0.21414573980230114f; + representations[67].kappas[2] = 0.6630219638878598f; + representations[67].normalizations[2] = 0.14367175560038878f; + representations[67].weights[3] = 0.0f; + representations[67].meanCosines[3] = 0.0f; + representations[67].kappas[3] = 0.0f; + representations[67].normalizations[3] = 0.0f; + + representations[68].K = 3; + representations[68].g = 0.5300787401574802f; + representations[68].weights[0] = 0.15201802364423217f; + representations[68].meanCosines[0] = 0.9045210208344292f; + representations[68].kappas[0] = 10.852964167601495f; + representations[68].normalizations[0] = 1.7273028951195475f; + representations[68].weights[1] = 0.435365524307831f; + representations[68].meanCosines[1] = 0.6828783513636263f; + representations[68].kappas[1] = 3.2420223660584204f; + representations[68].normalizations[1] = 0.5167733180958464f; + representations[68].weights[2] = 0.41261645204793684f; + representations[68].meanCosines[2] = 0.2169492083133833f; + representations[68].kappas[2] = 0.6722785944850328f; + representations[68].normalizations[2] = 0.14471792788382354f; + representations[68].weights[3] = 0.0f; + representations[68].meanCosines[3] = 0.0f; + representations[68].kappas[3] = 0.0f; + representations[68].normalizations[3] = 0.0f; + + representations[69].K = 3; + representations[69].g = 0.5378740157480315f; + representations[69].weights[0] = 0.15729294132110566f; + representations[69].meanCosines[0] = 0.9072830203855161f; + representations[69].kappas[0] = 11.168487946406515f; + representations[69].normalizations[0] = 1.7775200638868365f; + representations[69].weights[1] = 0.43599216989551043f; + representations[69].meanCosines[1] = 0.6881595863609994f; + representations[69].kappas[1] = 3.3025669779058386f; + representations[69].normalizations[1] = 0.5263321984049527f; + representations[69].weights[2] = 0.4067148887833839f; + representations[69].meanCosines[2] = 0.21974347919085768f; + representations[69].kappas[2] = 0.6815287539431827f; + representations[69].normalizations[2] = 0.1457671702417904f; + representations[69].weights[3] = 0.0f; + representations[69].meanCosines[3] = 0.0f; + representations[69].kappas[3] = 0.0f; + representations[69].normalizations[3] = 0.0f; + + representations[70].K = 3; + representations[70].g = 0.5456692913385827f; + representations[70].weights[0] = 0.1627091674945393f; + representations[70].meanCosines[0] = 0.9099831724121029f; + representations[70].kappas[0] = 11.495452369732478f; + representations[70].normalizations[0] = 1.8295580679098282f; + representations[70].weights[1] = 0.43652135984600265f; + representations[70].meanCosines[1] = 0.6933653968776663f; + representations[70].kappas[1] = 3.364035938949523f; + representations[70].normalizations[1] = 0.5360445070649383f; + representations[70].weights[2] = 0.40076947265945795f; + representations[70].meanCosines[2] = 0.22252895888323956f; + representations[70].kappas[2] = 0.690773965537422f; + representations[70].normalizations[2] = 0.1468196300804049f; + representations[70].weights[3] = 0.0f; + representations[70].meanCosines[3] = 0.0f; + representations[70].kappas[3] = 0.0f; + representations[70].normalizations[3] = 0.0f; + + representations[71].K = 3; + representations[71].g = 0.5534645669291338f; + representations[71].weights[0] = 0.16826931509786597f; + representations[71].meanCosines[0] = 0.9126237466462465f; + representations[71].kappas[0] = 11.834538906133483f; + representations[71].normalizations[0] = 1.883525366223493f; + representations[71].weights[1] = 0.436949287161954f; + representations[71].meanCosines[1] = 0.6984986216586416f; + representations[71].kappas[1] = 3.426477782827816f; + representations[71].normalizations[1] = 0.545917545079653f; + representations[71].weights[2] = 0.39478139774018f; + representations[71].meanCosines[2] = 0.22530605709251292f; + representations[71].kappas[2] = 0.7000157749339841f; + representations[71].normalizations[2] = 0.14787545977774874f; + representations[71].weights[3] = 0.0f; + representations[71].meanCosines[3] = 0.0f; + representations[71].kappas[3] = 0.0f; + representations[71].normalizations[3] = 0.0f; + + representations[72].K = 3; + representations[72].g = 0.561259842519685f; + representations[72].weights[0] = 0.17397605681486036f; + representations[72].meanCosines[0] = 0.91520688470064f; + representations[72].kappas[0] = 12.186480389405208f; + representations[72].normalizations[0] = 1.9395385929167108f; + representations[72].weights[1] = 0.4372720921624159f; + representations[72].meanCosines[1] = 0.7035620560829642f; + representations[72].kappas[1] = 3.4899440461679654f; + representations[72].normalizations[1] = 0.555959114489885f; + representations[72].weights[2] = 0.3887518510227237f; + representations[72].meanCosines[2] = 0.22807521187546123f; + representations[72].kappas[2] = 0.7092558347125714f; + representations[72].normalizations[2] = 0.1489348264074376f; + representations[72].weights[3] = 0.0f; + representations[72].meanCosines[3] = 0.0f; + representations[72].kappas[3] = 0.0f; + representations[72].normalizations[3] = 0.0f; + + representations[73].K = 3; + representations[73].g = 0.5690551181102362f; + representations[73].weights[0] = 0.17983214378421922f; + representations[73].meanCosines[0] = 0.9177346040817985f; + representations[73].kappas[0] = 12.552065355633442f; + representations[73].normalizations[0] = 1.997723247386592f; + representations[73].weights[1] = 0.4374858568977017f; + representations[73].meanCosines[1] = 0.7085584413162697f; + representations[73].kappas[1] = 3.554489351229144f; + representations[73].normalizations[1] = 0.5661775306041705f; + representations[73].weights[2] = 0.38268199931807917f; + representations[73].meanCosines[2] = 0.23083688408868736f; + representations[73].kappas[2] = 0.7184958875618854f; + representations[73].normalizations[2] = 0.1499979099875054f; + representations[73].weights[3] = 0.0f; + representations[73].meanCosines[3] = 0.0f; + representations[73].kappas[3] = 0.0f; + representations[73].normalizations[3] = 0.0f; + + representations[74].K = 3; + representations[74].g = 0.5768503937007874f; + representations[74].weights[0] = 0.1858404095572948f; + representations[74].meanCosines[0] = 0.9202088063452304f; + representations[74].kappas[0] = 12.93214347991311f; + representations[74].normalizations[0] = 2.0582145596138406f; + representations[74].weights[1] = 0.4375866002297341f; + representations[74].meanCosines[1] = 0.7134904673435183f; + representations[74].kappas[1] = 3.620171668163421f; + representations[74].normalizations[1] = 0.5765816626610434f; + representations[74].weights[2] = 0.376572990212971f; + representations[74].meanCosines[2] = 0.23359155944610333f; + representations[74].kappas[2] = 0.7277377748041182f; + representations[74].normalizations[2] = 0.15106490461580072f; + representations[74].weights[3] = 0.0f; + representations[74].meanCosines[3] = 0.0f; + representations[74].kappas[3] = 0.0f; + representations[74].normalizations[3] = 0.0f; + + representations[75].K = 3; + representations[75].g = 0.5846456692913385f; + representations[75].weights[0] = 0.1920037740311606f; + representations[75].meanCosines[0] = 0.9226312846743214f; + representations[75].kappas[0] = 13.327631663072642f; + representations[75].normalizations[0] = 2.1211584588916965f; + representations[75].weights[1] = 0.4375702730069559f; + representations[75].meanCosines[1] = 0.7183607762114199f; + representations[75].kappas[1] = 3.68705260568459f; + representations[75].normalizations[1] = 0.587180979062321f; + representations[75].weights[2] = 0.3704259529618835f; + representations[75].meanCosines[2] = 0.23633975076704322f; + representations[75].kappas[2] = 0.7369834457308975f; + representations[75].normalizations[2] = 0.15213601971801666f; + representations[75].weights[3] = 0.0f; + representations[75].meanCosines[3] = 0.0f; + representations[75].kappas[3] = 0.0f; + representations[75].normalizations[3] = 0.0f; + + representations[76].K = 3; + representations[76].g = 0.5924409448818897f; + representations[76].weights[0] = 0.19832522506414976f; + representations[76].meanCosines[0] = 0.9250037361138848f; + representations[76].kappas[0] = 13.739521789305007f; + representations[76].normalizations[0] = 2.1867128084892404f; + representations[76].weights[1] = 0.43743275979935015f; + representations[76].meanCosines[1] = 0.7231719821313055f; + representations[76].kappas[1] = 3.755197973339379f; + representations[76].normalizations[1] = 0.5979856357457428f; + representations[76].weights[2] = 0.3642420151365001f; + representations[76].meanCosines[2] = 0.23908201028376885f; + representations[76].kappas[2] = 0.7462350011130275f; + representations[76].normalizations[2] = 0.15321148529531584f; + representations[76].weights[3] = 0.0f; + representations[76].meanCosines[3] = 0.0f; + representations[76].kappas[3] = 0.0f; + representations[76].normalizations[3] = 0.0f; + + representations[77].K = 3; + representations[77].g = 0.600236220472441f; + representations[77].weights[0] = 0.2046370452946239f; + representations[77].meanCosines[0] = 0.9273696065000837f; + representations[77].kappas[0] = 14.176868423187258f; + representations[77].normalizations[0] = 2.2563186871147516f; + representations[77].weights[1] = 0.43734456589562715f; + representations[77].meanCosines[1] = 0.7279873281080078f; + representations[77].kappas[1] = 3.82557869797969f; + representations[77].normalizations[1] = 0.6091494065393616f; + representations[77].weights[2] = 0.35801838880974884f; + representations[77].meanCosines[2] = 0.2418089043788005f; + representations[77].kappas[2] = 0.7554607295835146f; + representations[77].normalizations[2] = 0.15428758395409456f; + representations[77].weights[3] = 0.0f; + representations[77].meanCosines[3] = 0.0f; + representations[77].kappas[3] = 0.0f; + representations[77].normalizations[3] = 0.0f; + + representations[78].K = 3; + representations[78].g = 0.6080314960629921f; + representations[78].weights[0] = 0.21145522532501376f; + representations[78].meanCosines[0] = 0.9296047853907953f; + representations[78].kappas[0] = 14.61687501213509f; + representations[78].normalizations[0] = 2.3263479107381757f; + representations[78].weights[1] = 0.43677719515994007f; + representations[78].meanCosines[1] = 0.732627039434998f; + representations[78].kappas[1] = 3.8955627628160325f; + representations[78].normalizations[1] = 0.6202544751769821f; + representations[78].weights[2] = 0.35176757951504606f; + representations[78].meanCosines[2] = 0.24455092610935678f; + representations[78].kappas[2] = 0.7647642149394f; + representations[78].normalizations[2] = 0.15537640901792682f; + representations[78].weights[3] = 0.0f; + representations[78].meanCosines[3] = 0.0f; + representations[78].kappas[3] = 0.0f; + representations[78].normalizations[3] = 0.0f; + + representations[79].K = 3; + representations[79].g = 0.6158267716535433f; + representations[79].weights[0] = 0.21827030956844096f; + representations[79].meanCosines[0] = 0.9318363148472478f; + representations[79].kappas[0] = 15.0847624352229f; + representations[79].normalizations[0] = 2.400814506932851f; + representations[79].weights[1] = 0.4362504726325965f; + representations[79].meanCosines[1] = 0.7372758864789994f; + representations[79].kappas[1] = 3.9679362147525175f; + representations[79].normalizations[1] = 0.6317426240166054f; + representations[79].weights[2] = 0.3454792177989626f; + representations[79].meanCosines[2] = 0.24727883164854889f; + representations[79].kappas[2] = 0.7740466736698095f; + representations[79].normalizations[2] = 0.15646641319686902f; + representations[79].weights[3] = 0.0f; + representations[79].meanCosines[3] = 0.0f; + representations[79].kappas[3] = 0.0f; + representations[79].normalizations[3] = 0.0f; + + representations[80].K = 3; + representations[80].g = 0.6236220472440944f; + representations[80].weights[0] = 0.22525660341537493f; + representations[80].meanCosines[0] = 0.9340236772779147f; + representations[80].kappas[0] = 15.573919583003752f; + representations[80].normalizations[0] = 2.47866628495079f; + representations[80].weights[1] = 0.43558520774587756f; + representations[80].meanCosines[1] = 0.741875590576798f; + representations[80].kappas[1] = 4.0418826507574455f; + representations[80].normalizations[1] = 0.6434841227651966f; + representations[80].weights[2] = 0.3391581888387475f; + representations[80].meanCosines[2] = 0.25000328942163386f; + representations[80].kappas[2] = 0.7833445758656036f; + representations[80].normalizations[2] = 0.15756185584196966f; + representations[80].weights[3] = 0.0f; + representations[80].meanCosines[3] = 0.0f; + representations[80].kappas[3] = 0.0f; + representations[80].normalizations[3] = 0.0f; + + representations[81].K = 3; + representations[81].g = 0.6314173228346457f; + representations[81].weights[0] = 0.23241776175313703f; + representations[81].meanCosines[0] = 0.9361681219135087f; + representations[81].kappas[0] = 16.085837543042345f; + representations[81].normalizations[0] = 2.560140558748405f; + representations[81].weights[1] = 0.43477678714167f; + representations[81].meanCosines[1] = 0.7464284999133005f; + representations[81].kappas[1] = 4.117492199043666f; + representations[81].normalizations[1] = 0.6554930806692963f; + representations[81].weights[2] = 0.3328054511051931f; + representations[81].meanCosines[2] = 0.25272498180459707f; + representations[81].kappas[2] = 0.7926605874210905f; + representations[81].normalizations[2] = 0.15866305057516353f; + representations[81].weights[3] = 0.0f; + representations[81].meanCosines[3] = 0.0f; + representations[81].kappas[3] = 0.0f; + representations[81].normalizations[3] = 0.0f; + + representations[82].K = 3; + representations[82].g = 0.6392125984251968f; + representations[82].weights[0] = 0.23975751170874146f; + representations[82].meanCosines[0] = 0.938270840447678f; + representations[82].kappas[0] = 16.622146439652063f; + representations[82].normalizations[0] = 2.6454967706679846f; + representations[82].weights[1] = 0.4338205035338164f; + representations[82].meanCosines[1] = 0.7509369787660656f; + representations[82].kappas[1] = 4.19486225496789f; + representations[82].normalizations[1] = 0.6677847773966972f; + representations[82].weights[2] = 0.326421984757442f; + representations[82].meanCosines[2] = 0.2554446622503517f; + representations[82].kappas[2] = 0.8019976488252991f; + representations[82].normalizations[2] = 0.15977034747756208f; + representations[82].weights[3] = 0.0f; + representations[82].meanCosines[3] = 0.0f; + representations[82].kappas[3] = 0.0f; + representations[82].normalizations[3] = 0.0f; + + representations[83].K = 3; + representations[83].g = 0.647007874015748f; + representations[83].weights[0] = 0.2472797267392922f; + representations[83].meanCosines[0] = 0.9403329568840185f; + representations[83].kappas[0] = 17.184628287927787f; + representations[83].normalizations[0] = 2.735018537220525f; + representations[83].weights[1] = 0.4327115257623153f; + representations[83].meanCosines[1] = 0.755403364106f; + representations[83].kappas[1] = 4.274097395549266f; + representations[83].normalizations[1] = 0.6803756490612852f; + representations[83].weights[2] = 0.32000874749839253f; + representations[83].meanCosines[2] = 0.25816313034840566f; + representations[83].kappas[2] = 0.8113588939736538f; + representations[83].normalizations[2] = 0.16088412390685938f; + representations[83].weights[3] = 0.0f; + representations[83].meanCosines[3] = 0.0f; + representations[83].kappas[3] = 0.0f; + representations[83].normalizations[3] = 0.0f; + + representations[84].K = 3; + representations[84].g = 0.6548031496062992f; + representations[84].weights[0] = 0.25498843647079295f; + representations[84].meanCosines[0] = 0.9423555310229852f; + representations[84].kappas[0] = 17.775234863783915f; + representations[84].normalizations[0] = 2.8290164931906037f; + representations[84].weights[1] = 0.4314448895810194f; + representations[84].meanCosines[1] = 0.7598299689358737f; + representations[84].kappas[1] = 4.3553100825444515f; + representations[84].normalizations[1] = 0.6932833994669038f; + representations[84].weights[2] = 0.31356667394818777f; + representations[84].meanCosines[2] = 0.26088123558629017f; + representations[84].kappas[2] = 0.8207476668897828f; + representations[84].normalizations[2] = 0.1620047868302051f; + representations[84].weights[3] = 0.0f; + representations[84].meanCosines[3] = 0.0f; + representations[84].kappas[3] = 0.0f; + representations[84].normalizations[3] = 0.0f; + + representations[85].K = 3; + representations[85].g = 0.6625984251968504f; + representations[85].weights[0] = 0.26288783702158497f; + representations[85].meanCosines[0] = 0.9443395617200645f; + representations[85].kappas[0] = 18.396108136191025f; + representations[85].normalizations[0] = 2.927831543527836f; + representations[85].weights[1] = 0.43001548795721395f; + representations[85].meanCosines[1] = 0.7642190859151877f; + representations[85].kappas[1] = 4.438621453366375f; + representations[85].normalizations[1] = 0.7065271253657252f; + representations[85].weights[2] = 0.3070966750212011f; + representations[85].meanCosines[2] = 0.26359988157208303f; + representations[85].kappas[2] = 0.8301675404574355f; + representations[85].normalizations[2] = 0.1631327754356981f; + representations[85].weights[3] = 0.0f; + representations[85].meanCosines[3] = 0.0f; + representations[85].kappas[3] = 0.0f; + representations[85].normalizations[3] = 0.0f; + + representations[86].K = 3; + representations[86].g = 0.6703937007874016f; + representations[86].weights[0] = 0.2709823025842266f; + representations[86].meanCosines[0] = 0.946285989794297f; + representations[86].kappas[0] = 19.04960365116869f; + representations[86].normalizations[0] = 3.0318385850249148f; + representations[86].weights[1] = 0.42841806009583794f; + representations[86].meanCosines[1] = 0.7685729910925694f; + representations[86].kappas[1] = 4.524162209037049f; + representations[86].normalizations[1] = 0.7201274571932929f; + representations[86].weights[2] = 0.30059963731993555f; + representations[86].meanCosines[2] = 0.26632003080603134f; + representations[86].kappas[2] = 0.8396223375305958f; + representations[86].normalizations[2] = 0.1642685640724313f; + representations[86].weights[3] = 0.0f; + representations[86].meanCosines[3] = 0.0f; + representations[86].kappas[3] = 0.0f; + representations[86].normalizations[3] = 0.0f; + + representations[87].K = 3; + representations[87].g = 0.6781889763779527f; + representations[87].weights[0] = 0.27927639895625234f; + representations[87].meanCosines[0] = 0.9481957005904299f; + representations[87].kappas[0] = 19.738317362685333f; + representations[87].normalizations[0] = 3.141450776587954f; + representations[87].weights[1] = 0.42664717956103104f; + representations[87].meanCosines[1] = 0.7728939469951241f; + representations[87].kappas[1] = 4.6120735976093465f; + representations[87].normalizations[1] = 0.7341067150314727f; + representations[87].weights[2] = 0.2940764214827166f; + representations[87].meanCosines[2] = 0.26904270916915274f; + representations[87].kappas[2] = 0.8491161515891782f; + representations[87].normalizations[2] = 0.16541266518389522f; + representations[87].weights[3] = 0.0f; + representations[87].meanCosines[3] = 0.0f; + representations[87].kappas[3] = 0.0f; + representations[87].normalizations[3] = 0.0f; + + representations[88].K = 3; + representations[88].g = 0.6859842519685039f; + representations[88].weights[0] = 0.28777489737254797f; + representations[88].meanCosines[0] = 0.950069526417547f; + representations[88].kappas[0] = 20.46511658959084f; + representations[88].normalizations[0] = 3.257124466185333f; + representations[88].weights[1] = 0.4246972411959944f; + representations[88].meanCosines[1] = 0.777184206751141f; + representations[88].kappas[1] = 4.702508541381448f; + representations[88].normalizations[1] = 0.7484890874829961f; + representations[88].weights[2] = 0.2875278614314578f; + representations[88].meanCosines[2] = 0.27176901175720886f; + representations[88].kappas[2] = 0.8586533726595088f; + representations[88].normalizations[2] = 0.16656563292649454f; + representations[88].weights[3] = 0.0f; + representations[88].meanCosines[3] = 0.0f; + representations[88].kappas[3] = 0.0f; + representations[88].normalizations[3] = 0.0f; + + representations[89].K = 3; + representations[89].g = 0.6937795275590551f; + representations[89].weights[0] = 0.29648279054616156f; + representations[89].meanCosines[0] = 0.9519082486667635f; + representations[89].kappas[0] = 21.233175767008145f; + representations[89].normalizations[0] = 3.3793648808583927f; + representations[89].weights[1] = 0.42256244663705916f; + representations[89].meanCosines[1] = 0.7814460177839457f; + representations[89].kappas[1] = 4.79563289895453f; + representations[89].normalizations[1] = 0.7633008320368476f; + representations[89].weights[2] = 0.2809547628167793f; + representations[89].meanCosines[2] = 0.27450010877501546f; + representations[89].kappas[2] = 0.8682387141297602f; + representations[89].normalizations[2] = 0.16772806695708195f; + representations[89].weights[3] = 0.0f; + representations[89].meanCosines[3] = 0.0f; + representations[89].kappas[3] = 0.0f; + representations[89].normalizations[3] = 0.0f; + + representations[90].K = 3; + representations[90].g = 0.7015748031496063f; + representations[90].weights[0] = 0.30540725904987076f; + representations[90].meanCosines[0] = 0.9537123443474214f; + representations[90].kappas[0] = 22.04589839813786f; + representations[90].normalizations[0] = 3.508713704965338f; + representations[90].weights[1] = 0.4202357317039357f; + representations[90].meanCosines[1] = 0.7856805379542191f; + representations[90].kappas[1] = 4.891601785632994f; + representations[90].normalizations[1] = 0.7785665078511023f; + representations[90].weights[2] = 0.27435700924619355f; + representations[90].meanCosines[2] = 0.27723648769685544f; + representations[90].kappas[2] = 0.8778745463929781f; + representations[90].normalizations[2] = 0.16890028814166394f; + representations[90].weights[3] = 0.0f; + representations[90].meanCosines[3] = 0.0f; + representations[90].kappas[3] = 0.0f; + representations[90].normalizations[3] = 0.0f; + + representations[91].K = 3; + representations[91].g = 0.7093700787401575f; + representations[91].weights[0] = 0.314550142879425f; + representations[91].meanCosines[0] = 0.9554829884712971f; + representations[91].kappas[0] = 22.907423174275007f; + representations[91].normalizations[0] = 3.645829631683703f; + representations[91].weights[1] = 0.41771281013698197f; + representations[91].meanCosines[1] = 0.7898920757285216f; + representations[91].kappas[1] = 4.990657929218684f; + representations[91].normalizations[1] = 0.7943246211247126f; + representations[91].weights[2] = 0.2677370469835929f; + representations[91].meanCosines[2] = 0.2799809273695421f; + representations[91].kappas[2] = 0.887571384710121f; + representations[91].normalizations[2] = 0.1700836159252505f; + representations[91].weights[3] = 0.0f; + representations[91].meanCosines[3] = 0.0f; + representations[91].kappas[3] = 0.0f; + representations[91].normalizations[3] = 0.0f; + + representations[92].K = 3; + representations[92].g = 0.7171653543307086f; + representations[92].weights[0] = 0.323918941281032f; + representations[92].meanCosines[0] = 0.9572205847121196f; + representations[92].kappas[0] = 23.822020537466877f; + representations[92].normalizations[0] = 3.791392322974503f; + representations[92].weights[1] = 0.41498628744100596f; + representations[92].meanCosines[1] = 0.7940819034205951f; + representations[92].kappas[1] = 5.092993495012177f; + representations[92].normalizations[1] = 0.8106056455269498f; + representations[92].weights[2] = 0.2610947712779621f; + representations[92].meanCosines[2] = 0.282734183473497f; + representations[92].kappas[2] = 0.8973327073543883f; + representations[92].normalizations[2] = 0.17127852245500216f; + representations[92].weights[3] = 0.0f; + representations[92].meanCosines[3] = 0.0f; + representations[92].kappas[3] = 0.0f; + representations[92].normalizations[3] = 0.0f; + + representations[93].K = 3; + representations[93].g = 0.7249606299212599f; + representations[93].weights[0] = 0.33351973492144515f; + representations[93].meanCosines[0] = 0.9589257276203178f; + representations[93].kappas[0] = 24.794582197555773f; + representations[93].normalizations[0] = 3.9461803186393105f; + representations[93].weights[1] = 0.4120494090831267f; + representations[93].meanCosines[1] = 0.7982522854579217f; + representations[93].kappas[1] = 5.198842429689294f; + representations[93].normalizations[1] = 0.8274467106645826f; + representations[93].weights[2] = 0.2544308559954282f; + representations[93].meanCosines[2] = 0.28549779909773215f; + representations[93].kappas[2] = 0.9071648530197196f; + representations[93].normalizations[2] = 0.17248583639675724f; + representations[93].weights[3] = 0.0f; + representations[93].meanCosines[3] = 0.0f; + representations[93].kappas[3] = 0.0f; + representations[93].normalizations[3] = 0.0f; + + representations[94].K = 3; + representations[94].g = 0.732755905511811f; + representations[94].weights[0] = 0.34335893848221183f; + representations[94].meanCosines[0] = 0.9605989682723478f; + representations[94].kappas[0] = 25.830596813856708f; + representations[94].normalizations[0] = 4.111067165939057f; + representations[94].weights[1] = 0.4088951248319031f; + representations[94].meanCosines[1] = 0.8024055019653422f; + representations[94].kappas[1] = 5.308461053986367f; + representations[94].normalizations[1] = 0.844888514968835f; + representations[94].weights[2] = 0.24774593668588507f; + representations[94].meanCosines[2] = 0.28827343354031715f; + representations[94].kappas[2] = 0.9170746723463243f; + representations[94].normalizations[2] = 0.17370645864779166f; + representations[94].weights[3] = 0.0f; + representations[94].meanCosines[3] = 0.0f; + representations[94].kappas[3] = 0.0f; + representations[94].normalizations[3] = 0.0f; + + representations[95].K = 3; + representations[95].g = 0.7405511811023622f; + representations[95].weights[0] = 0.3534433331276196f; + representations[95].meanCosines[0] = 0.9622408150553718f; + representations[95].kappas[0] = 26.936241870352298f; + representations[95].normalizations[0] = 4.2870360419854485f; + representations[95].weights[1] = 0.4055160595500465f; + representations[95].meanCosines[1] = 0.8065438531577983f; + representations[95].kappas[1] = 5.4221308324173805f; + representations[95].normalizations[1] = 0.862975766145269f; + representations[95].weights[2] = 0.241040607322334f; + representations[95].meanCosines[2] = 0.29106287302029366f; + representations[95].kappas[2] = 0.9270695781955348f; + representations[95].normalizations[2] = 0.1749413695318436f; + representations[95].weights[3] = 0.0f; + representations[95].meanCosines[3] = 0.0f; + representations[95].kappas[3] = 0.0f; + representations[95].normalizations[3] = 0.0f; + + representations[96].K = 3; + representations[96].g = 0.7483464566929133f; + representations[96].weights[0] = 0.3637801026569973f; + representations[96].meanCosines[0] = 0.9638517343301604f; + representations[96].kappas[0] = 28.11849281221908f; + representations[96].normalizations[0] = 4.475197123358596f; + representations[96].weights[1] = 0.4019044800572026f; + representations[96].meanCosines[1] = 0.8106696644633893f; + representations[96].kappas[1] = 5.540161579519249f; + representations[96].normalizations[1] = 0.8817576911146353f; + representations[96].weights[2] = 0.23431541728580002f; + representations[96].meanCosines[2] = 0.2938680432362927f; + representations[96].kappas[2] = 0.937157604192799f; + representations[96].normalizations[2] = 0.17619163714893982f; + representations[96].weights[3] = 0.0f; + representations[96].meanCosines[3] = 0.0f; + representations[96].kappas[3] = 0.0f; + representations[96].normalizations[3] = 0.0f; + + representations[97].K = 3; + representations[97].g = 0.7561417322834645f; + representations[97].weights[0] = 0.3743768742282063f; + representations[97].meanCosines[0] = 0.9654321509327287f; + representations[97].kappas[0] = 29.385253280066383f; + representations[97].normalizations[0] = 4.676808313529897f; + representations[97].weights[1] = 0.3980522577175622f; + representations[97].meanCosines[1] = 0.8147852920835721f; + representations[97].kappas[1] = 5.662895174359178f; + representations[97].normalizations[1] = 0.9012886268604031f; + representations[97].weights[2] = 0.22757086805423143f; + representations[97].meanCosines[2] = 0.2966910234570728f; + representations[97].kappas[2] = 0.947347470721517f; + representations[97].normalizations[2] = 0.17745842680432455f; + representations[97].weights[3] = 0.0f; + representations[97].meanCosines[3] = 0.0f; + representations[97].kappas[3] = 0.0f; + representations[97].normalizations[3] = 0.0f; + + representations[98].K = 3; + representations[98].g = 0.7639370078740157f; + representations[98].weights[0] = 0.38524176513689695f; + representations[98].meanCosines[0] = 0.9669824484448641f; + representations[98].kappas[0] = 30.745511243403147f; + representations[98].normalizations[0] = 4.893300092275056f; + representations[98].weights[1] = 0.39395082537468784f; + representations[98].meanCosines[1] = 0.8188931287879918f; + representations[98].kappas[1] = 5.790709872115165f; + representations[98].normalizations[1] = 0.921628706315985f; + representations[98].weights[2] = 0.22080740948841507f; + representations[98].meanCosines[2] = 0.29953406232822644f; + representations[98].kappas[2] = 0.9576486593632786f; + representations[98].normalizations[2] = 0.1787430116657337f; + representations[98].weights[3] = 0.0f; + representations[98].meanCosines[3] = 0.0f; + representations[98].kappas[3] = 0.0f; + representations[98].normalizations[3] = 0.0f; + + representations[99].K = 3; + representations[99].g = 0.7717322834645669f; + representations[99].weights[0] = 0.3963834354896696f; + representations[99].meanCosines[0] = 0.9685029693213756f; + representations[99].kappas[0] = 32.20952726109539f; + representations[99].normalizations[0] = 5.126305478256488f; + representations[99].weights[1] = 0.389591128435386f; + representations[99].meanCosines[1] = 0.8229956105366834f; + representations[99].kappas[1] = 5.924025346530906f; + representations[99].normalizations[1] = 0.9428446605844728f; + representations[99].weights[2] = 0.21402543607494445f; + representations[99].meanCosines[2] = 0.30239959610284156f; + representations[99].kappas[2] = 0.9680714987483626f; + representations[99].normalizations[2] = 0.1800467850491632f; + representations[99].weights[3] = 0.0f; + representations[99].meanCosines[3] = 0.0f; + representations[99].kappas[3] = 0.0f; + representations[99].normalizations[3] = 0.0f; + + representations[100].K = 3; + representations[100].g = 0.7795275590551181f; + representations[100].weights[0] = 0.40781114817626546f; + representations[100].meanCosines[0] = 0.9699940148344911f; + representations[100].kappas[0] = 33.78906273533941f; + representations[100].normalizations[0] = 5.377696356771425f; + representations[100].weights[1] = 0.384963568809248f; + representations[100].meanCosines[1] = 0.8270952239166515f; + representations[100].kappas[1] = 6.0633086088731885f; + representations[100].normalizations[1] = 0.9650107606665378f; + representations[100].weights[2] = 0.20722528301448653f; + representations[100].meanCosines[2] = 0.3052902696089327f; + representations[100].kappas[2] = 0.9786272634654758f; + representations[100].normalizations[2] = 0.18137127457879043f; + representations[100].weights[3] = 0.0f; + representations[100].meanCosines[3] = 0.0f; + representations[100].kappas[3] = 0.0f; + representations[100].normalizations[3] = 0.0f; + + representations[101].K = 3; + representations[101].g = 0.7873228346456692f; + representations[101].weights[0] = 0.41953483679279924f; + representations[101].meanCosines[0] = 0.9714558448595689f; + representations[101].kappas[0] = 35.49765836096025f; + representations[101].normalizations[0] = 5.649627796334172f; + representations[101].weights[1] = 0.3800579408710988f; + representations[101].meanCosines[1] = 0.8311945147568722f; + representations[101].kappas[1] = 6.209080996730074f; + representations[101].normalizations[1] = 0.9882099294651575f; + representations[101].weights[2] = 0.2004072223361021f; + representations[101].meanCosines[2] = 0.3082089606822717f; + representations[101].kappas[2] = 0.9893282893087417f; + representations[101].normalizations[2] = 0.18271815867924948f; + representations[101].weights[3] = 0.0f; + representations[101].meanCosines[3] = 0.0f; + representations[101].kappas[3] = 0.0f; + representations[101].normalizations[3] = 0.0f; + + representations[102].K = 3; + representations[102].g = 0.7951181102362205f; + representations[102].weights[0] = 0.4315651834971288f; + representations[102].meanCosines[0] = 0.9728886774534552f; + representations[102].kappas[0] = 37.35097594771657f; + representations[102].normalizations[0] = 5.944592451385582f; + representations[102].weights[1] = 0.3748633576315606f; + representations[102].meanCosines[1] = 0.8352960978646506f; + representations[102].kappas[1] = 6.361926458461669f; + representations[102].normalizations[1] = 1.0125350600042866f; + representations[102].weights[2] = 0.1935714588713106f; + representations[102].meanCosines[2] = 0.3111588084871263f; + representations[102].kappas[2] = 1.0001881071793164f; + representations[102].normalizations[2] = 0.18408928574987296f; + representations[102].weights[3] = 0.0f; + representations[102].meanCosines[3] = 0.0f; + representations[102].kappas[3] = 0.0f; + representations[102].normalizations[3] = 0.0f; + + representations[103].K = 3; + representations[103].g = 0.8029133858267716f; + representations[103].weights[0] = 0.44391370756781706f; + representations[103].meanCosines[0] = 0.9742926882438233f; + representations[103].kappas[0] = 39.367220961959f; + representations[103].normalizations[0] = 6.265487811886654f; + representations[103].weights[1] = 0.36936816605135847f; + representations[103].meanCosines[1] = 0.8394026685967423f; + representations[103].kappas[1] = 6.522501446086053f; + representations[103].normalizations[1] = 1.038090589640147f; + representations[103].weights[2] = 0.18671812638082452f; + representations[103].meanCosines[2] = 0.31414324697871443f; + representations[103].kappas[2] = 1.0112216011955533f; + representations[103].normalizations[2] = 0.18548669679179886f; + representations[103].weights[3] = 0.0f; + representations[103].meanCosines[3] = 0.0f; + representations[103].kappas[3] = 0.0f; + representations[103].normalizations[3] = 0.0f; + + representations[104].K = 3; + representations[104].g = 0.8107086614173228f; + representations[104].weights[0] = 0.4565928655077412f; + representations[104].meanCosines[0] = 0.9756680097086392f; + representations[104].kappas[0] = 41.567668857394764f; + representations[104].normalizations[0] = 6.615699971461414f; + representations[104].weights[1] = 0.3635598499248879f; + representations[104].meanCosines[1] = 0.8435170173064288f; + representations[104].kappas[1] = 6.691546828263287f; + representations[104].normalizations[1] = 1.0649943957813093f; + representations[104].weights[2] = 0.17984728456737106f; + representations[104].meanCosines[2] = 0.3171660455034625f; + representations[104].kappas[2] = 1.0224451996197383f; + representations[104].normalizations[2] = 0.18691265266954193f; + representations[104].weights[3] = 0.0f; + representations[104].meanCosines[3] = 0.0f; + representations[104].kappas[3] = 0.0f; + representations[104].normalizations[3] = 0.0f; + + representations[105].K = 3; + representations[105].g = 0.8185039370078739f; + representations[105].weights[0] = 0.4696161649129583f; + representations[105].meanCosines[0] = 0.977014730283103f; + representations[105].kappas[0] = 43.97732584501906f; + representations[105].normalizations[0] = 6.999208792197747f; + representations[105].weights[1] = 0.35742491854950126f; + representations[105].meanCosines[1] = 0.84764204686941f; + representations[105].kappas[1] = 6.869902315309078f; + representations[105].normalizations[1] = 1.093380091409223f; + representations[105].weights[2] = 0.17295891653754053f; + representations[105].meanCosines[2] = 0.32023135742690917f; + representations[105].kappas[2] = 1.0338771035147776f; + representations[105].normalizations[2] = 0.18836966675060354f; + representations[105].weights[3] = 0.0f; + representations[105].meanCosines[3] = 0.0f; + representations[105].kappas[3] = 0.0f; + representations[105].normalizations[3] = 0.0f; + + representations[106].K = 3; + representations[106].g = 0.8262992125984252f; + representations[106].weights[0] = 0.4829982941672016f; + representations[106].meanCosines[0] = 0.9783328932720207f; + representations[106].kappas[0] = 46.62576555511482f; + representations[106].normalizations[0] = 7.420721063540353f; + representations[106].weights[1] = 0.35094877818208203f; + representations[106].meanCosines[1] = 0.8517807946686041f; + representations[106].kappas[1] = 7.058524082784808f; + representations[106].normalizations[1] = 1.1233998296647842f; + representations[106].weights[2] = 0.16605292765071641f; + representations[106].meanCosines[2] = 0.3233437801620528f; + representations[106].kappas[2] = 1.0455375677314898f; + representations[106].normalizations[2] = 0.18986054493140442f; + representations[106].weights[3] = 0.0f; + representations[106].meanCosines[3] = 0.0f; + representations[106].kappas[3] = 0.0f; + representations[106].normalizations[3] = 0.0f; + + representations[107].K = 3; + representations[107].g = 0.8340944881889764f; + representations[107].weights[0] = 0.4967552695533019f; + representations[107].meanCosines[0] = 0.9796224956118234f; + representations[107].kappas[0] = 49.548198396402306f; + representations[107].normalizations[0] = 7.885840696085349f; + representations[107].weights[1] = 0.34411558431336736f; + representations[107].meanCosines[1] = 0.8559364605914935f; + representations[107].kappas[1] = 7.258506499478957f; + representations[107].normalizations[1] = 1.155227761664598f; + representations[107].weights[2] = 0.15912914613333057f; + representations[107].meanCosines[2] = 0.32650842986505385f; + representations[107].kappas[2] = 1.0574492492183072f; + representations[107].normalizations[2] = 0.19138843516693316f; + representations[107].weights[3] = 0.0f; + representations[107].meanCosines[3] = 0.0f; + representations[107].kappas[3] = 0.0f; + representations[107].normalizations[3] = 0.0f; + + representations[108].K = 3; + representations[108].g = 0.8418897637795275f; + representations[108].weights[0] = 0.5109046020998166f; + representations[108].meanCosines[0] = 0.9808834864797452f; + representations[108].kappas[0] = 52.786852197566795f; + representations[108].normalizations[0] = 8.401288457504034f; + representations[108].weights[1] = 0.3369080716212091f; + representations[108].meanCosines[1] = 0.8601124431065127f; + representations[108].kappas[1] = 7.471109181727082f; + representations[108].normalizations[1] = 1.1890643420250768f; + representations[108].weights[2] = 0.15218732627897416f; + representations[108].meanCosines[2] = 0.329731035892612f; + representations[108].kappas[2] = 1.069637645498256f; + representations[108].normalizations[2] = 0.19295688969917166f; + representations[108].weights[3] = 0.0f; + representations[108].meanCosines[3] = 0.0f; + representations[108].kappas[3] = 0.0f; + representations[108].normalizations[3] = 0.0f; + + representations[109].K = 3; + representations[109].g = 0.8496850393700787f; + representations[109].weights[0] = 0.5254626731586894f; + representations[109].meanCosines[0] = 0.9821159342861068f; + representations[109].kappas[0] = 56.39330160029513f; + representations[109].normalizations[0] = 8.975272706959062f; + representations[109].weights[1] = 0.3293094541752853f; + representations[109].meanCosines[1] = 0.8643135954007387f; + representations[109].kappas[1] = 7.69785828048804f; + representations[109].normalizations[1] = 1.2251524488594658f; + representations[109].weights[2] = 0.14522787266602524f; + representations[109].meanCosines[2] = 0.333019161366721f; + representations[109].kappas[2] = 1.0821358440292181f; + representations[109].normalizations[2] = 0.19457048614110656f; + representations[109].weights[3] = 0.0f; + representations[109].meanCosines[3] = 0.0f; + representations[109].kappas[3] = 0.0f; + representations[109].normalizations[3] = 0.0f; + + representations[110].K = 3; + representations[110].g = 0.8574803149606299f; + representations[110].weights[0] = 0.5404523430049603f; + representations[110].meanCosines[0] = 0.98331956425316f; + representations[110].kappas[0] = 60.429586611677735f; + representations[110].normalizations[0] = 9.617667418248331f; + representations[110].weights[1] = 0.3212977300181286f; + representations[110].meanCosines[1] = 0.8685431140960943f; + representations[110].kappas[1] = 7.940423625414496f; + representations[110].normalizations[1] = 1.2637578304420414f; + representations[110].weights[2] = 0.1382499269769111f; + representations[110].meanCosines[2] = 0.3363795356492694f; + representations[110].kappas[2] = 1.094974535419832f; + representations[110].normalizations[2] = 0.19623354919267594f; + representations[110].weights[3] = 0.0f; + representations[110].meanCosines[3] = 0.0f; + representations[110].kappas[3] = 0.0f; + representations[110].normalizations[3] = 0.0f; + + representations[111].K = 3; + representations[111].g = 0.8652755905511811f; + representations[111].weights[0] = 0.5559119561109656f; + representations[111].meanCosines[0] = 0.9844933366024191f; + representations[111].kappas[0] = 64.96899206355937f; + representations[111].normalizations[0] = 10.340136234613592f; + representations[111].weights[1] = 0.31283862434945703f; + representations[111].meanCosines[1] = 0.8727988632471873f; + representations[111].kappas[1] = 8.20040365631985f; + representations[111].normalizations[1] = 1.3051348756250123f; + representations[111].weights[2] = 0.13124941953957747f; + representations[111].meanCosines[2] = 0.339814518724571f; + representations[111].kappas[2] = 1.1081683784152283f; + representations[111].normalizations[2] = 0.19794837195289897f; + representations[111].weights[3] = 0.0f; + representations[111].meanCosines[3] = 0.0f; + representations[111].kappas[3] = 0.0f; + representations[111].normalizations[3] = 0.0f; + + representations[112].K = 3; + representations[112].g = 0.8730708661417322f; + representations[112].weights[0] = 0.5718393884942973f; + representations[112].meanCosines[0] = 0.9856385541741431f; + representations[112].kappas[0] = 70.11289450093315f; + representations[112].normalizations[0] = 11.158813734304077f; + representations[112].weights[1] = 0.3039279013397253f; + representations[112].meanCosines[1] = 0.877097567216021f; + representations[112].kappas[1] = 8.480895648432082f; + representations[112].normalizations[1] = 1.3497765223508311f; + representations[112].weights[2] = 0.12423271016597735f; + representations[112].meanCosines[2] = 0.34334507908236944f; + representations[112].kappas[2] = 1.1218045936162597f; + representations[112].normalizations[2] = 0.1997267555056942f; + representations[112].weights[3] = 0.0f; + representations[112].meanCosines[3] = 0.0f; + representations[112].kappas[3] = 0.0f; + representations[112].normalizations[3] = 0.0f; + + representations[113].K = 3; + representations[113].g = 0.8808661417322834f; + representations[113].weights[0] = 0.5882755569376641f; + representations[113].meanCosines[0] = 0.9867541732199454f; + representations[113].kappas[0] = 75.97889680688574f; + representations[113].normalizations[0] = 12.09241699748489f; + representations[113].weights[1] = 0.29452813547870665f; + representations[113].meanCosines[1] = 0.8814393829516305f; + representations[113].kappas[1] = 8.784435438014446f; + representations[113].normalizations[1] = 1.3980863550011564f; + representations[113].weights[2] = 0.11719630758362938f; + representations[113].meanCosines[2] = 0.34697797664221613f; + representations[113].kappas[2] = 1.1359172624615688f; + representations[113].normalizations[2] = 0.201573696281553f; + representations[113].weights[3] = 0.0f; + representations[113].meanCosines[3] = 0.0f; + representations[113].kappas[3] = 0.0f; + representations[113].normalizations[3] = 0.0f; + + representations[114].K = 3; + representations[114].g = 0.8886614173228347f; + representations[114].weights[0] = 0.6052504230780653f; + representations[114].meanCosines[0] = 0.9878398850719791f; + representations[114].kappas[0] = 82.7208461258252f; + representations[114].normalizations[0] = 13.165431557669141f; + representations[114].weights[1] = 0.28460934660642634f; + representations[114].meanCosines[1] = 0.8858313360968593f; + representations[114].kappas[1] = 9.114532078598165f; + representations[114].normalizations[1] = 1.450622851848577f; + representations[114].weights[2] = 0.11014023031550828f; + representations[114].meanCosines[2] = 0.35072796340726353f; + representations[114].kappas[2] = 1.1505728992115452f; + representations[114].normalizations[2] = 0.20349852757540107f; + representations[114].weights[3] = 0.0f; + representations[114].meanCosines[3] = 0.0f; + representations[114].kappas[3] = 0.0f; + representations[114].normalizations[3] = 0.0f; + + representations[115].K = 3; + representations[115].g = 0.8964566929133858f; + representations[115].weights[0] = 0.6228027995524672f; + representations[115].meanCosines[0] = 0.9888950555229361f; + representations[115].kappas[0] = 90.53608079149387f; + representations[115].normalizations[0] = 14.409264786133447f; + representations[115].weights[1] = 0.2741336567223465f; + representations[115].meanCosines[1] = 0.8902793797177282f; + representations[115].kappas[1] = 9.475314166168351f; + representations[115].normalizations[1] = 1.5080430957712354f; + representations[115].weights[2] = 0.10306354372518628f; + representations[115].meanCosines[2] = 0.35461082756841766f; + representations[115].kappas[2] = 1.1658441284758267f; + representations[115].normalizations[2] = 0.20551152432759512f; + representations[115].weights[3] = 0.0f; + representations[115].meanCosines[3] = 0.0f; + representations[115].kappas[3] = 0.0f; + representations[115].normalizations[3] = 0.0f; + + representations[116].K = 3; + representations[116].g = 0.904251968503937f; + representations[116].weights[0] = 0.6409625400276326f; + representations[116].meanCosines[0] = 0.9899195955960743f; + representations[116].kappas[0] = 99.68975599147025f; + representations[116].normalizations[0] = 15.866117441667381f; + representations[116].weights[1] = 0.2630691381584243f; + representations[116].meanCosines[1] = 0.8947966101812765f; + representations[116].kappas[1] = 9.872432613573858f; + representations[116].normalizations[1] = 1.571246454971746f; + representations[116].weights[2] = 0.095968321813943f; + representations[116].meanCosines[2] = 0.35865262749978183f; + representations[116].kappas[2] = 1.1818467475255494f; + representations[116].normalizations[2] = 0.20762883801820764f; + representations[116].weights[3] = 0.0f; + representations[116].meanCosines[3] = 0.0f; + representations[116].kappas[3] = 0.0f; + representations[116].normalizations[3] = 0.0f; + + representations[117].K = 3; + representations[117].g = 0.9120472440944881f; + representations[117].weights[0] = 0.6597760942835212f; + representations[117].meanCosines[0] = 0.990912757734808f; + representations[117].kappas[0] = 110.53301707231405f; + representations[117].normalizations[0] = 17.59187604191964f; + representations[117].weights[1] = 0.2513693157615257f; + representations[117].meanCosines[1] = 0.8993933442306955f; + representations[117].kappas[1] = 10.312609687465988f; + representations[117].normalizations[1] = 1.6413028097479578f; + representations[117].weights[2] = 0.08885458995495317f; + representations[117].meanCosines[2] = 0.3628812013801927f; + representations[117].kappas[2] = 1.1987075268355516f; + representations[117].normalizations[2] = 0.20986833173806205f; + representations[117].weights[3] = 0.0f; + representations[117].meanCosines[3] = 0.0f; + representations[117].kappas[3] = 0.0f; + representations[117].normalizations[3] = 0.0f; + + representations[118].K = 3; + representations[118].g = 0.9198425196850394f; + representations[118].weights[0] = 0.6792894636829033f; + representations[118].meanCosines[0] = 0.9918739739911012f; + representations[118].kappas[0] = 123.55121730910922f; + representations[118].normalizations[0] = 19.663786959765673f; + representations[118].weights[1] = 0.23898619212136155f; + representations[118].meanCosines[1] = 0.90408570736703f; + representations[118].kappas[1] = 10.804874085633132f; + representations[118].normalizations[1] = 1.719649120922708f; + representations[118].weights[2] = 0.0817243441957352f; + representations[118].meanCosines[2] = 0.3673375775419639f; + representations[118].kappas[2] = 1.2166110601123843f; + representations[118].normalizations[2] = 0.2122558873307257f; + representations[118].weights[3] = 0.0f; + representations[118].meanCosines[3] = 0.0f; + representations[118].kappas[3] = 0.0f; + representations[118].normalizations[3] = 0.0f; + + representations[119].K = 3; + representations[119].g = 0.9276377952755905f; + representations[119].weights[0] = 0.6995522112361258f; + representations[119].meanCosines[0] = 0.9928026697072287f; + representations[119].kappas[0] = 139.4314038120058f; + representations[119].normalizations[0] = 22.191197138922863f; + representations[119].weights[1] = 0.22586650550479143f; + representations[119].meanCosines[1] = 0.9088960661837021f; + representations[119].kappas[1] = 11.361507506541727f; + representations[119].normalizations[1] = 1.8082400808865704f; + representations[119].weights[2] = 0.07458128325908273f; + representations[119].meanCosines[2] = 0.3720816407633235f; + representations[119].kappas[2] = 1.2358257584794836f; + representations[119].normalizations[2] = 0.21482908030767447f; + representations[119].weights[3] = 0.0f; + representations[119].meanCosines[3] = 0.0f; + representations[119].kappas[3] = 0.0f; + representations[119].normalizations[3] = 0.0f; + + representations[120].K = 3; + representations[120].g = 0.9354330708661417f; + representations[120].weights[0] = 0.7206159394099868f; + representations[120].meanCosines[0] = 0.9936983266077104f; + representations[120].kappas[0] = 159.18012629540559f; + representations[120].normalizations[0] = 25.33430394190599f; + representations[120].weights[1] = 0.2119520463912963f; + representations[120].meanCosines[1] = 0.9138572737432618f; + representations[120].kappas[1] = 11.999993458215888f; + representations[120].normalizations[1] = 1.9098582760175666f; + representations[120].weights[2] = 0.06743201419871682f; + representations[120].meanCosines[2] = 0.37720700329635093f; + representations[120].kappas[2] = 1.2567696961188874f; + representations[120].normalizations[2] = 0.2176463521023088f; + representations[120].weights[3] = 0.0f; + representations[120].meanCosines[3] = 0.0f; + representations[120].kappas[3] = 0.0f; + representations[120].normalizations[3] = 0.0f; + + representations[121].K = 3; + representations[121].g = 0.9432283464566928f; + representations[121].weights[0] = 0.7425298903086794f; + representations[121].meanCosines[0] = 0.9945606294046142f; + representations[121].kappas[0] = 184.33799721904487f; + representations[121].normalizations[0] = 29.338303457071046f; + representations[121].weights[1] = 0.19718172827509786f; + representations[121].meanCosines[1] = 0.9190211970423342f; + representations[121].kappas[1] = 12.746832832976239f; + representations[121].normalizations[1] = 2.028721454151434f; + representations[121].weights[2] = 0.06028838141622271f; + representations[121].meanCosines[2] = 0.3828729966523628f; + representations[121].kappas[2] = 1.2801527883158197f; + representations[121].normalizations[2] = 0.22080684477938303f; + representations[121].weights[3] = 0.0f; + representations[121].meanCosines[3] = 0.0f; + representations[121].kappas[3] = 0.0f; + representations[121].normalizations[3] = 0.0f; + + representations[122].K = 3; + representations[122].g = 0.9510236220472441f; + representations[122].weights[0] = 0.7653293103607429f; + representations[122].meanCosines[0] = 0.9953898118117097f; + representations[122].kappas[0] = 217.4051196152159f; + representations[122].normalizations[0] = 34.60109944024639f; + representations[122].weights[1] = 0.18149838112785868f; + representations[122].meanCosines[1] = 0.9244773850283557f; + representations[122].kappas[1] = 13.64592273008513f; + representations[122].normalizations[1] = 2.1718160555461488f; + representations[122].weights[2] = 0.05317230851139854f; + representations[122].meanCosines[2] = 0.3893806024131917f; + representations[122].kappas[2] = 1.3073167675130757f; + representations[122].normalizations[2] = 0.22449796615062265f; + representations[122].weights[3] = 0.0f; + representations[122].meanCosines[3] = 0.0f; + representations[122].kappas[3] = 0.0f; + representations[122].normalizations[3] = 0.0f; + + representations[123].K = 3; + representations[123].g = 0.9588188976377953f; + representations[123].weights[0] = 0.7890052405183582f; + representations[123].meanCosines[0] = 0.9961874879915438f; + representations[123].kappas[0] = 262.7894883431296f; + representations[123].normalizations[0] = 41.82424606239909f; + representations[123].weights[1] = 0.16486806075823146f; + representations[123].meanCosines[1] = 0.9303977710641655f; + representations[123].kappas[1] = 14.779725799317857f; + representations[123].normalizations[1] = 2.352266418504593f; + representations[123].weights[2] = 0.04612669872341031f; + representations[123].meanCosines[2] = 0.3973748382479435f; + representations[123].kappas[2] = 1.3411535562102717f; + representations[123].normalizations[2] = 0.22912451559489155f; + representations[123].weights[3] = 0.0f; + representations[123].meanCosines[3] = 0.0f; + representations[123].kappas[3] = 0.0f; + representations[123].normalizations[3] = 0.0f; + + representations[124].K = 3; + representations[124].g = 0.9666141732283464f; + representations[124].weights[0] = 0.8134132864130297f; + representations[124].meanCosines[0] = 0.9969590951155314f; + representations[124].kappas[0] = 329.34568100402697f; + representations[124].normalizations[0] = 52.41699311775743f; + representations[124].weights[1] = 0.14734309576502963f; + representations[124].meanCosines[1] = 0.9371602294155938f; + representations[124].kappas[1] = 16.334429702579303f; + representations[124].normalizations[1] = 2.599705229752591f; + representations[124].weights[2] = 0.03924361782194063f; + representations[124].meanCosines[2] = 0.4084766247518925f; + representations[124].kappas[2] = 1.38903995811237f; + representations[124].normalizations[2] = 0.2357246896803882f; + representations[124].weights[3] = 0.0f; + representations[124].meanCosines[3] = 0.0f; + representations[124].kappas[3] = 0.0f; + representations[124].normalizations[3] = 0.0f; + + representations[125].K = 3; + representations[125].g = 0.9744094488188976f; + representations[125].weights[0] = 0.8380377885238703f; + representations[125].meanCosines[0] = 0.9977192495345887f; + representations[125].kappas[0] = 438.9493224499256f; + representations[125].normalizations[0] = 69.86095443474393f; + representations[125].weights[1] = 0.12922359501050967f; + representations[125].meanCosines[1] = 0.9456890221956583f; + representations[125].kappas[1] = 18.84421609415959f; + representations[125].normalizations[1] = 2.999150140077348f; + representations[125].weights[2] = 0.03273861646562f; + representations[125].meanCosines[2] = 0.42761937604381417f; + representations[125].kappas[2] = 1.4742417480145642f; + representations[125].normalizations[2] = 0.24761249545923705f; + representations[125].weights[3] = 0.0f; + representations[125].meanCosines[3] = 0.0f; + representations[125].kappas[3] = 0.0f; + representations[125].normalizations[3] = 0.0f; + + representations[126].K = 3; + representations[126].g = 0.9822047244094488f; + representations[126].weights[0] = 0.86110354278221f; + representations[126].meanCosines[0] = 0.9985077831939306f; + representations[126].kappas[0] = 670.6420411084238f; + representations[126].normalizations[0] = 106.73599588764372f; + representations[126].weights[1] = 0.11170062456703932f; + representations[126].meanCosines[1] = 0.958498099808663f; + representations[126].kappas[1] = 24.543185034997688f; + representations[126].normalizations[1] = 3.906169217538914f; + representations[126].weights[2] = 0.027195832650750658f; + representations[126].meanCosines[2] = 0.47512959398520177f; + representations[126].kappas[2] = 1.7024552564942006f; + representations[126].normalizations[2] = 0.28026159880811696f; + representations[126].weights[3] = 0.0f; + representations[126].meanCosines[3] = 0.0f; + representations[126].kappas[3] = 0.0f; + representations[126].normalizations[3] = 0.0f; + + representations[127].K = 3; + representations[127].g = 0.99f; + representations[127].weights[0] = 0.868073622158317f; + representations[127].meanCosines[0] = 0.9994691382373244f; + representations[127].kappas[0] = 1884.2289065113011f; + representations[127].normalizations[0] = 299.88434438791035f; + representations[127].weights[1] = 0.10584342660588578f; + representations[127].meanCosines[1] = 0.9844441544134342f; + representations[127].kappas[1] = 64.76504041838344f; + representations[127].normalizations[1] = 10.307676322132117f; + representations[127].weights[2] = 0.026082951235797305f; + representations[127].meanCosines[2] = 0.7491038510925567f; + representations[127].kappas[2] = 4.163095340893173f; + representations[127].normalizations[2] = 0.6627376458781823f; + representations[127].weights[3] = 0.0f; + representations[127].meanCosines[3] = 0.0f; + representations[127].kappas[3] = 0.0f; + representations[127].normalizations[3] = 0.0f; +} +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/directional/vmm/VMMPhaseFunctions.h b/openpgl/directional/vmm/VMMPhaseFunctions.h index f161b1d..eb2bc92 100644 --- a/openpgl/directional/vmm/VMMPhaseFunctions.h +++ b/openpgl/directional/vmm/VMMPhaseFunctions.h @@ -3,10 +3,11 @@ #pragma once -#include "../../openpgl_common.h" +#include #include -#include + +#include "../../openpgl_common.h" #define OPENPGL_VMM_NUM_PHASE_COMP 4 @@ -16,45 +17,44 @@ namespace openpgl { - struct VMMPhaseFunctionRepresentation - { - int K {OPENPGL_VMM_NUM_PHASE_COMP}; - float g {0.f}; - float weights[OPENPGL_VMM_NUM_PHASE_COMP]; - float meanCosines[OPENPGL_VMM_NUM_PHASE_COMP]; - float kappas[OPENPGL_VMM_NUM_PHASE_COMP]; - float normalizations[OPENPGL_VMM_NUM_PHASE_COMP]; +struct VMMPhaseFunctionRepresentation +{ + int K{OPENPGL_VMM_NUM_PHASE_COMP}; + float g{0.f}; + float weights[OPENPGL_VMM_NUM_PHASE_COMP]; + float meanCosines[OPENPGL_VMM_NUM_PHASE_COMP]; + float kappas[OPENPGL_VMM_NUM_PHASE_COMP]; + float normalizations[OPENPGL_VMM_NUM_PHASE_COMP]; - //const std::string toString() const{ + // const std::string toString() const{ - //} - }; + //} +}; +class VMMSingleLobeHenyeyGreensteinOracle +{ + static float minMeanCosine; //{0.f}; + static float maxMeanCosine; //{0.99f}; + static int numRepresentations; //{128}; + public: + static std::array representations; + + static void init(); - class VMMSingleLobeHenyeyGreensteinOracle + static const VMMPhaseFunctionRepresentation &getPhaseFunctionRepresentation(const float meanCosine) { - static float minMeanCosine; //{0.f}; - static float maxMeanCosine; //{0.99f}; - static int numRepresentations; //{128}; - public: - static std::array representations; - - static void init(); - - static const VMMPhaseFunctionRepresentation &getPhaseFunctionRepresentation(const float meanCosine) - { - //OPENPGL_ASSERT(std::fabs(meanCosine) >= minMeanCosine); - //OPENPGL_ASSERT(std::fabs(meanCosine) <= maxMeanCosine); - - const float absMeanCosine = std::fabs(meanCosine); - const float stepSize = (maxMeanCosine-minMeanCosine)/float(numRepresentations); - int idx = std::floor((absMeanCosine-minMeanCosine)/stepSize); - idx = std::min(idx, numRepresentations-1); - - OPENPGL_ASSERT(idx >= 0); - OPENPGL_ASSERT(idx < numRepresentations); - return representations[idx]; - } - }; - -} + // OPENPGL_ASSERT(std::fabs(meanCosine) >= minMeanCosine); + // OPENPGL_ASSERT(std::fabs(meanCosine) <= maxMeanCosine); + + const float absMeanCosine = std::fabs(meanCosine); + const float stepSize = (maxMeanCosine - minMeanCosine) / float(numRepresentations); + int idx = std::floor((absMeanCosine - minMeanCosine) / stepSize); + idx = std::min(idx, numRepresentations - 1); + + OPENPGL_ASSERT(idx >= 0); + OPENPGL_ASSERT(idx < numRepresentations); + return representations[idx]; + } +}; + +} // namespace openpgl diff --git a/openpgl/directional/vmm/VMMSurfaceSamplingDistribution.h b/openpgl/directional/vmm/VMMSurfaceSamplingDistribution.h index 5869088..b0ba74f 100644 --- a/openpgl/directional/vmm/VMMSurfaceSamplingDistribution.h +++ b/openpgl/directional/vmm/VMMSurfaceSamplingDistribution.h @@ -3,21 +3,21 @@ #pragma once -#include "../ISurfaceSamplingDistribution.h" - #include +#include "../ISurfaceSamplingDistribution.h" + namespace openpgl { -template -struct __aligned(TVMMDistribution::VectorSize*4) VMMSurfaceSamplingDistribution: public ISurfaceSamplingDistribution +template +struct __aligned(TVMMDistribution::VectorSize * 4) VMMSurfaceSamplingDistribution : public ISurfaceSamplingDistribution { - OPENPGL_ALIGNED_STRUCT_(TVMMDistribution::VectorSize*4) + OPENPGL_ALIGNED_STRUCT_(TVMMDistribution::VectorSize * 4) - VMMSurfaceSamplingDistribution() {}; + VMMSurfaceSamplingDistribution(){}; ~VMMSurfaceSamplingDistribution() override = default; - + typedef std::integral_constant MaxNumProductDistributions; /// the region's Li distribution with applied parallax-compensation @@ -28,17 +28,17 @@ struct __aligned(TVMMDistribution::VectorSize*4) VMMSurfaceSamplingDistribution: /// distribution sampling weights, sum up to 1.0f std::array m_weights; /// when 0 use the non-product distribution instead - uint32_t m_numDistributions {0}; + uint32_t m_numDistributions{0}; /// guiding cosine/BSDF product integral (= irradiance/flux, for cosine) - float m_productIntegral {0.f}; + float m_productIntegral{0.f}; - const IRegion* m_region {nullptr}; + const IRegion *m_region{nullptr}; - inline void init(const void* distribution, Point3 samplePosition) override + inline void init(const void *distribution, Point3 samplePosition) override { - m_liDistribution = *(const TVMMDistribution*)distribution; + m_liDistribution = *(const TVMMDistribution *)distribution; // prespare sampling distribution - if(UseParallaxCompensation) + if (UseParallaxCompensation) { const Point3 pivotPosition = this->m_liDistribution._pivotPosition; this->m_liDistribution.performRelativeParallaxShift(pivotPosition - samplePosition); @@ -49,11 +49,11 @@ struct __aligned(TVMMDistribution::VectorSize*4) VMMSurfaceSamplingDistribution: this->m_productIntegral = 1.0f; } - inline void applyCosineProduct(const Vector3& normal) override + inline void applyCosineProduct(const Vector3 &normal) override { const float cosine_kappa = 2.18853f; - const float cosine_normalization = 2.18853f/(2.0f*M_PI_F*(1.0f-std::exp(-2.0f * 2.18853f))); - if(this->m_numDistributions > 0) + const float cosine_normalization = 2.18853f / (2.0f * M_PI_F * (1.0f - std::exp(-2.0f * 2.18853f))); + if (this->m_numDistributions > 0) { this->m_productIntegral = this->m_distributions[0].product(1.0f, normal, cosine_kappa, cosine_normalization); } @@ -68,11 +68,11 @@ struct __aligned(TVMMDistribution::VectorSize*4) VMMSurfaceSamplingDistribution: { OPENPGL_ASSERT(m_numDistributions > 0); - float weight {0.0f}; - uint32_t i=0; - for (; i sample.x) break; @@ -80,7 +80,7 @@ struct __aligned(TVMMDistribution::VectorSize*4) VMMSurfaceSamplingDistribution: weight = nextWeight; } - Vector3 dir = m_distributions[i].sample(openpgl::Vector2{(sample.x-weight)/m_weights[i], sample.y}); + Vector3 dir = m_distributions[i].sample(openpgl::Vector2{(sample.x - weight) / m_weights[i], sample.y}); return Vector3(dir[0], dir[1], dir[2]); } @@ -89,9 +89,9 @@ struct __aligned(TVMMDistribution::VectorSize*4) VMMSurfaceSamplingDistribution: { OPENPGL_ASSERT(m_numDistributions > 0); - float pdf {0.0f}; - for (uint32_t i=0; i -struct __aligned(TVMMDistribution::VectorSize*4) VMMVolumeSamplingDistribution: public IVolumeSamplingDistribution +template +struct __aligned(TVMMDistribution::VectorSize * 4) VMMVolumeSamplingDistribution : public IVolumeSamplingDistribution { - - OPENPGL_ALIGNED_STRUCT_(TVMMDistribution::VectorSize*4) - VMMVolumeSamplingDistribution(): IVolumeSamplingDistribution(){}; + OPENPGL_ALIGNED_STRUCT_(TVMMDistribution::VectorSize * 4) + VMMVolumeSamplingDistribution() : IVolumeSamplingDistribution(){}; ~VMMVolumeSamplingDistribution() override = default; typedef std::integral_constant MaxNumProductDistributions; @@ -27,20 +26,20 @@ struct __aligned(TVMMDistribution::VectorSize*4) VMMVolumeSamplingDistribution: /// distribution sampling weights, sum up to 1.0f std::array m_weights; /// when 0 use the non-product distribution instead - uint32_t m_numDistributions {0}; + uint32_t m_numDistributions{0}; /// guiding cosine/BSDF product integral (= irradiance/flux, for cosine) - float m_productIntegral {0.f}; + float m_productIntegral{0.f}; - const IRegion* m_region {nullptr}; + const IRegion *m_region{nullptr}; - inline void init(const void* distribution, Point3 samplePosition) override + inline void init(const void *distribution, Point3 samplePosition) override { - m_liDistribution = *(TVMMDistribution*)distribution; + m_liDistribution = *(TVMMDistribution *)distribution; - //m_liDistribution.uniformInit(0.0); + // m_liDistribution.uniformInit(0.0); // prespare sampling distribution - if(UseParallaxCompensation) + if (UseParallaxCompensation) { const Point3 pivotPosition = this->m_liDistribution._pivotPosition; this->m_liDistribution.performRelativeParallaxShift(pivotPosition - samplePosition); @@ -51,30 +50,30 @@ struct __aligned(TVMMDistribution::VectorSize*4) VMMVolumeSamplingDistribution: this->m_productIntegral = 1.0f; } - inline void applySingleLobeHenyeyGreensteinProduct(const Vector3& dir, const float meanCosine) override + inline void applySingleLobeHenyeyGreensteinProduct(const Vector3 &dir, const float meanCosine) override { - float sumWeights = 0.f; - const VMMPhaseFunctionRepresentation pfRep =VMMSingleLobeHenyeyGreensteinOracle::getPhaseFunctionRepresentation(meanCosine); + float sumWeights = 0.f; + const VMMPhaseFunctionRepresentation pfRep = VMMSingleLobeHenyeyGreensteinOracle::getPhaseFunctionRepresentation(meanCosine); - for (int i=0; i < pfRep.K; i++) + for (int i = 0; i < pfRep.K; i++) { this->m_distributions[i] = m_liDistribution; - const Vector3 outDir = meanCosine * pfRep.meanCosines[i] > 0.f ? dir: -dir; - /* + const Vector3 outDir = meanCosine * pfRep.meanCosines[i] > 0.f ? dir : -dir; + /* const float absMeanCosine = std::fabs(pfRep.meanCosines[i]); float kappa = MeanCosineToKappa< float >(absMeanCosine); kappa = kappa<= 1e-4f ? 0.0f: kappa; this->m_weights[i] = this->m_distributions[i].product(pfRep.weights[i], outDir, kappa); - */ + */ this->m_weights[i] = this->m_distributions[i].product(pfRep.weights[i], outDir, pfRep.kappas[i], pfRep.normalizations[i]); sumWeights += this->m_weights[i]; } - for (int i=0; i< pfRep.K; i++) + for (int i = 0; i < pfRep.K; i++) { - this->m_weights[i] /=sumWeights; + this->m_weights[i] /= sumWeights; } - + this->m_numDistributions = pfRep.K; this->m_productIntegral = sumWeights; } @@ -88,11 +87,11 @@ struct __aligned(TVMMDistribution::VectorSize*4) VMMVolumeSamplingDistribution: { OPENPGL_ASSERT(m_numDistributions > 0); - float weight {0.0f}; - uint32_t i=0; - for (; i sample.x) break; @@ -100,7 +99,7 @@ struct __aligned(TVMMDistribution::VectorSize*4) VMMVolumeSamplingDistribution: weight = nextWeight; } - Vector3 dir = m_distributions[i].sample(openpgl::Vector2{(sample.x-weight)/m_weights[i], sample.y}); + Vector3 dir = m_distributions[i].sample(openpgl::Vector2{(sample.x - weight) / m_weights[i], sample.y}); return Vector3(dir[0], dir[1], dir[2]); } @@ -109,9 +108,9 @@ struct __aligned(TVMMDistribution::VectorSize*4) VMMVolumeSamplingDistribution: { OPENPGL_ASSERT(m_numDistributions > 0); - float pdf {0.0f}; - for (uint32_t i=0; i 0.f ? dir: -dir; + const Vector3 outDir = meanCosine * pfRep.meanCosines[i] > 0.f ? dir : -dir; inscatteredRad += pfRep.weights[i] * m_liDistribution.inscatteredRadiance(outDir, pfRep.meanCosines[i], directLightMIS); } return inscatteredRad; @@ -154,7 +153,7 @@ struct __aligned(TVMMDistribution::VectorSize*4) VMMVolumeSamplingDistribution: inline Vector3 fluence(const bool directLightMIS) const override { return m_liDistribution.fluence(directLightMIS); - } + } #endif inline bool validate() const override @@ -171,23 +170,23 @@ struct __aligned(TVMMDistribution::VectorSize*4) VMMVolumeSamplingDistribution: { std::ostringstream oss; oss << "GuidingData [\n"; - for (uint32_t i=0; i class TSpatialStructureBuilder> +template class TSpatialStructureBuilder> struct Field { -public: - + public: using DirectionalDistributionFactory = TDirectionalDistributionFactory; using DirectionalDistributionFactorySettings = typename TDirectionalDistributionFactory::Configuration; using DirectionalDistribution = typename TDirectionalDistributionFactory::Distribution; @@ -39,25 +36,25 @@ struct Field typedef Region RegionType; typedef openpgl::Range RangeType; - typedef std::pair RegionStorageType; - typedef tbb::concurrent_vector< RegionStorageType > RegionStorageContainerType; + typedef std::pair RegionStorageType; + typedef tbb::concurrent_vector RegionStorageContainerType; - using SpatialStructureBuilder = TSpatialStructureBuilder; + using SpatialStructureBuilder = TSpatialStructureBuilder; using SpatialStructure = typename SpatialStructureBuilder::SpatialStructure; using SpatialBuilderSettings = typename SpatialStructureBuilder::Settings; struct DebugSettings { - bool fitRegions {true}; + bool fitRegions{true}; }; struct SpatialSettings { SpatialBuilderSettings spatialSubdivBuilderSettings; - bool useStochasticNNLookUp {false}; - bool useISNNLookUp {false}; - bool deterministic {false}; - float decayOnSpatialSplit {0.25f}; + bool useStochasticNNLookUp{false}; + bool useISNNLookUp{false}; + bool deterministic{false}; + float decayOnSpatialSplit{0.25f}; std::string toString() const; }; @@ -67,14 +64,13 @@ struct Field SpatialSettings settings; DirectionalDistributionFactorySettings distributionFactorySettings; DebugSettings debugSettings; - std::string toString()const; + std::string toString() const; }; -public: - + public: Field() = default; - Field(const Field&) = delete; + Field(const Field &) = delete; Field(const Settings &settings) { @@ -110,11 +106,11 @@ struct Field m_isSurface = isSurface; } - inline const RegionType *getRegion(const openpgl::Point3 &p, float *sample1D, uint32_t &id ) const + inline const RegionType *getRegion(const openpgl::Point3 &p, float *sample1D, uint32_t &id) const { - if (m_iteration >0 && embree::inside(m_spatialSubdiv.getBounds(), p)) + if (m_iteration > 0 && embree::inside(m_spatialSubdiv.getBounds(), p)) { - if(m_useStochasticNNLookUp && *sample1D >= 0.f) + if (m_useStochasticNNLookUp && *sample1D >= 0.f) { if (USE_PRECOMPUTED_NN) { @@ -123,8 +119,8 @@ struct Field } else { - uint32_t regionIdx = getClosestRegionIdx(m_regionKNNSearchTree, p, sample1D, id); - if(regionIdx != -1) + uint32_t regionIdx = getClosestRegionIdx(m_regionKNNSearchTree, p, sample1D, id); + if (regionIdx != -1) { return &m_regionStorageContainer[regionIdx].first; } @@ -148,51 +144,52 @@ struct Field } } - void buildField(const SampleContainer& samples) + void buildField(const SampleContainer &samples) { m_iteration = 0; - m_totalSPP = 0; - if(samples.samples.size() > 0) + m_totalSPP = 0; + if (samples.samples.size() > 0) { Timer updateAll; Timer updateStep; - - if(samples_.capacity() < samples.samples.size()) { + + if (samples_.capacity() < samples.samples.size()) + { samples_.reserve(2 * samples.samples.size()); } samples_.resize(samples.samples.size()); #ifdef USE_EMBREE_PARALLEL - embree::parallel_for( size_t(0), samples.samples.size(), size_t(4*4096), [&](const embree::range& r) { + embree::parallel_for(size_t(0), samples.samples.size(), size_t(4 * 4096), [&](const embree::range &r) { #else - tbb::parallel_for( tbb::blocked_range(0,samples.samples.size()), [&](tbb::blocked_range r) { + tbb::parallel_for(tbb::blocked_range(0, samples.samples.size()), [&](tbb::blocked_range r) { #endif - for (size_t i=r.begin(); i& r) { + embree::parallel_for(size_t(0), samples.zeroValueSamples.size(), size_t(4 * 4096), [&](const embree::range &r) { #else - tbb::parallel_for( tbb::blocked_range(0,samples.zeroValueSamples.size()), [&](tbb::blocked_range r) { + tbb::parallel_for(tbb::blocked_range(0, samples.zeroValueSamples.size()), [&](tbb::blocked_range r) { #endif - for (size_t i=r.begin(); i 0) + if (samples.samples.size() > 0) { Timer updateAll; Timer updateStep; - if(samples_.capacity() < samples.samples.size()) { + if (samples_.capacity() < samples.samples.size()) + { samples_.reserve(2 * samples.samples.size()); } samples_.resize(samples.samples.size()); #ifdef USE_EMBREE_PARALLEL - embree::parallel_for( size_t(0), samples.samples.size(), size_t(4*4096), [&](const embree::range& r) { + embree::parallel_for(size_t(0), samples.samples.size(), size_t(4 * 4096), [&](const embree::range &r) { #else - tbb::parallel_for( tbb::blocked_range(0,samples.samples.size()), [&](tbb::blocked_range r) { + tbb::parallel_for(tbb::blocked_range(0, samples.samples.size()), [&](tbb::blocked_range r) { #endif - for (size_t i=r.begin(); i& r) { + embree::parallel_for(size_t(0), samples.zeroValueSamples.size(), size_t(4 * 4096), [&](const embree::range &r) { #else - tbb::parallel_for( tbb::blocked_range(0,samples.zeroValueSamples.size()), [&](tbb::blocked_range r) { + tbb::parallel_for(tbb::blocked_range(0, samples.zeroValueSamples.size()), [&](tbb::blocked_range r) { #endif - for (size_t i=r.begin(); i(&m_isSurface), sizeof(m_isSurface)); - os.write(reinterpret_cast(&m_decayOnSpatialSplit), sizeof(m_decayOnSpatialSplit)); - os.write(reinterpret_cast(&m_iteration), sizeof(m_iteration)); - os.write(reinterpret_cast(&m_totalSPP), sizeof(m_totalSPP)); - os.write(reinterpret_cast(&m_deterministic), sizeof(m_deterministic)); - os.write(reinterpret_cast(&m_fitRegions), sizeof(m_fitRegions)); - os.write(reinterpret_cast(&m_isSceneBoundsSet), sizeof(m_isSceneBoundsSet)); - os.write(reinterpret_cast(&m_sceneBounds), sizeof(m_sceneBounds)); - os.write(reinterpret_cast(&m_initialized), sizeof(m_initialized)); - - os.write(reinterpret_cast(&m_timeLastUpdate), sizeof(m_timeLastUpdate)); - os.write(reinterpret_cast(&m_timeLastUpdateCopySamples), sizeof(m_timeLastUpdateCopySamples)); - os.write(reinterpret_cast(&m_timeLastUpdateSpatialStructureUpdate), sizeof(m_timeLastUpdateSpatialStructureUpdate)); - os.write(reinterpret_cast(&m_timeLastUpdateDirectionalDistriubtionUpdate), sizeof(m_timeLastUpdateDirectionalDistriubtionUpdate)); + void serialize(std::ostream &os) const + { + os.write(reinterpret_cast(&m_isSurface), sizeof(m_isSurface)); + os.write(reinterpret_cast(&m_decayOnSpatialSplit), sizeof(m_decayOnSpatialSplit)); + os.write(reinterpret_cast(&m_iteration), sizeof(m_iteration)); + os.write(reinterpret_cast(&m_totalSPP), sizeof(m_totalSPP)); + os.write(reinterpret_cast(&m_deterministic), sizeof(m_deterministic)); + os.write(reinterpret_cast(&m_fitRegions), sizeof(m_fitRegions)); + os.write(reinterpret_cast(&m_isSceneBoundsSet), sizeof(m_isSceneBoundsSet)); + os.write(reinterpret_cast(&m_sceneBounds), sizeof(m_sceneBounds)); + os.write(reinterpret_cast(&m_initialized), sizeof(m_initialized)); + + os.write(reinterpret_cast(&m_timeLastUpdate), sizeof(m_timeLastUpdate)); + os.write(reinterpret_cast(&m_timeLastUpdateCopySamples), sizeof(m_timeLastUpdateCopySamples)); + os.write(reinterpret_cast(&m_timeLastUpdateSpatialStructureUpdate), sizeof(m_timeLastUpdateSpatialStructureUpdate)); + os.write(reinterpret_cast(&m_timeLastUpdateDirectionalDistriubtionUpdate), sizeof(m_timeLastUpdateDirectionalDistriubtionUpdate)); m_distributionFactorySettings.serialize(os); m_spatialSubdivBuilderSettings.serialize(os); m_spatialSubdiv.serialize(os); size_t size = m_regionStorageContainer.size(); - os.write(reinterpret_cast(&size), sizeof(size)); - for (size_t i = 0; i < size; i++) { + os.write(reinterpret_cast(&size), sizeof(size)); + for (size_t i = 0; i < size; i++) + { m_regionStorageContainer[i].first.serialize(os); m_regionStorageContainer[i].second.serialize(os); } - os.write(reinterpret_cast(&m_useStochasticNNLookUp), sizeof(m_useStochasticNNLookUp)); - os.write(reinterpret_cast(&m_useISNNLookUp), sizeof(m_useISNNLookUp)); + os.write(reinterpret_cast(&m_useStochasticNNLookUp), sizeof(m_useStochasticNNLookUp)); + os.write(reinterpret_cast(&m_useISNNLookUp), sizeof(m_useISNNLookUp)); m_regionKNNSearchTree.serialize(os); } - void deserialize(std::istream& is) + void deserialize(std::istream &is) { - is.read(reinterpret_cast(&m_isSurface), sizeof(m_isSurface)); - is.read(reinterpret_cast(&m_decayOnSpatialSplit), sizeof(m_decayOnSpatialSplit)); - is.read(reinterpret_cast(&m_iteration), sizeof(m_iteration)); - is.read(reinterpret_cast(&m_totalSPP), sizeof(m_totalSPP)); - is.read(reinterpret_cast(&m_deterministic), sizeof(m_deterministic)); - is.read(reinterpret_cast(&m_fitRegions), sizeof(m_fitRegions)); - is.read(reinterpret_cast(&m_isSceneBoundsSet), sizeof(m_isSceneBoundsSet)); - is.read(reinterpret_cast(&m_sceneBounds), sizeof(m_sceneBounds)); - is.read(reinterpret_cast(&m_initialized), sizeof(m_initialized)); - - is.read(reinterpret_cast(&m_timeLastUpdate), sizeof(m_timeLastUpdate)); - is.read(reinterpret_cast(&m_timeLastUpdateCopySamples), sizeof(m_timeLastUpdateCopySamples)); - is.read(reinterpret_cast(&m_timeLastUpdateSpatialStructureUpdate), sizeof(m_timeLastUpdateSpatialStructureUpdate)); - is.read(reinterpret_cast(&m_timeLastUpdateDirectionalDistriubtionUpdate), sizeof(m_timeLastUpdateDirectionalDistriubtionUpdate)); + is.read(reinterpret_cast(&m_isSurface), sizeof(m_isSurface)); + is.read(reinterpret_cast(&m_decayOnSpatialSplit), sizeof(m_decayOnSpatialSplit)); + is.read(reinterpret_cast(&m_iteration), sizeof(m_iteration)); + is.read(reinterpret_cast(&m_totalSPP), sizeof(m_totalSPP)); + is.read(reinterpret_cast(&m_deterministic), sizeof(m_deterministic)); + is.read(reinterpret_cast(&m_fitRegions), sizeof(m_fitRegions)); + is.read(reinterpret_cast(&m_isSceneBoundsSet), sizeof(m_isSceneBoundsSet)); + is.read(reinterpret_cast(&m_sceneBounds), sizeof(m_sceneBounds)); + is.read(reinterpret_cast(&m_initialized), sizeof(m_initialized)); + + is.read(reinterpret_cast(&m_timeLastUpdate), sizeof(m_timeLastUpdate)); + is.read(reinterpret_cast(&m_timeLastUpdateCopySamples), sizeof(m_timeLastUpdateCopySamples)); + is.read(reinterpret_cast(&m_timeLastUpdateSpatialStructureUpdate), sizeof(m_timeLastUpdateSpatialStructureUpdate)); + is.read(reinterpret_cast(&m_timeLastUpdateDirectionalDistriubtionUpdate), sizeof(m_timeLastUpdateDirectionalDistriubtionUpdate)); m_distributionFactorySettings.deserialize(is); m_spatialSubdivBuilderSettings.deserialize(is); m_spatialSubdiv.deserialize(is); size_t size; - is.read(reinterpret_cast(&size), sizeof(size)); + is.read(reinterpret_cast(&size), sizeof(size)); m_regionStorageContainer.clear(); m_regionStorageContainer.reserve(size); - for (size_t i = 0; i < size; i++) { + for (size_t i = 0; i < size; i++) + { m_regionStorageContainer.emplace_back(); m_regionStorageContainer[i].first.deserialize(is); m_regionStorageContainer[i].second.deserialize(is); - } - is.read(reinterpret_cast(&m_useStochasticNNLookUp), sizeof(m_useStochasticNNLookUp)); - is.read(reinterpret_cast(&m_useISNNLookUp), sizeof(m_useISNNLookUp)); + is.read(reinterpret_cast(&m_useStochasticNNLookUp), sizeof(m_useStochasticNNLookUp)); + is.read(reinterpret_cast(&m_useISNNLookUp), sizeof(m_useISNNLookUp)); m_regionKNNSearchTree.deserialize(is); - if (m_useStochasticNNLookUp && USE_PRECOMPUTED_NN && m_regionKNNSearchTree.isBuild()) { + if (m_useStochasticNNLookUp && USE_PRECOMPUTED_NN && m_regionKNNSearchTree.isBuild()) + { m_regionKNNSearchTree.buildRegionNeighbours(); } } @@ -353,23 +354,22 @@ struct Field return m_initialized; } -private: - - void estimateSceneBounds(const SampleContainerInternal& samples) + private: + void estimateSceneBounds(const SampleContainerInternal &samples) { m_sceneBounds.lower = Vector3(std::numeric_limits::max()); m_sceneBounds.upper = Vector3(std::numeric_limits::min()); m_isSceneBoundsSet = false; - if(samples.size() > 0) + if (samples.size() > 0) { // TODO parallize this part (also use some stats?) - for (const auto& sample : samples) + for (const auto &sample : samples) { m_sceneBounds.extend(Vector3(sample.position.x, sample.position.y, sample.position.z)); } Vector3 center = m_sceneBounds.center(); - m_sceneBounds.lower = center + 3.0f * (m_sceneBounds.lower - center); + m_sceneBounds.lower = center + 3.0f * (m_sceneBounds.lower - center); m_sceneBounds.upper = center + 3.0f * (m_sceneBounds.upper - center); m_isSceneBoundsSet = true; } @@ -388,13 +388,13 @@ struct Field uint32_t dataIdx = m_spatialSubdiv.getDataIdxAtPos(p); OPENPGL_ASSERT(dataIdx < m_regionStorageContainer.size()); id = dataIdx; - if(m_useISNNLookUp) + if (m_useISNNLookUp) return knnTree.sampleApproximateClosestRegionIdxIS(dataIdx, p, sample); else return knnTree.sampleApproximateClosestRegionIdx(dataIdx, p, sample); } - inline void buildSpatialStructure(const BBox &bounds, SampleContainerInternal& samples) + inline void buildSpatialStructure(const BBox &bounds, SampleContainerInternal &samples) { m_spatialSubdivBuilder.build(m_spatialSubdiv, bounds, samples, m_regionStorageContainer, m_spatialSubdivBuilderSettings); if (m_useStochasticNNLookUp) @@ -407,7 +407,7 @@ struct Field } } - inline void updateSpatialStructure(SampleContainerInternal& samples, ZeroValueSampleContainerInternal& zeroValueSamples) + inline void updateSpatialStructure(SampleContainerInternal &samples, ZeroValueSampleContainerInternal &zeroValueSamples) { m_spatialSubdivBuilder.updateTree(m_spatialSubdiv, samples, m_regionStorageContainer, m_spatialSubdivBuilderSettings); m_spatialSubdivBuilder.insertTree(m_spatialSubdiv, zeroValueSamples, m_regionStorageContainer); @@ -422,235 +422,256 @@ struct Field } } - inline void fitRegions(SampleContainerInternal& samples, ZeroValueSampleContainerInternal& zeroValueSamples) + inline void fitRegions(SampleContainerInternal &samples, ZeroValueSampleContainerInternal &zeroValueSamples) { size_t nGuidingRegions = m_regionStorageContainer.size(); -#if defined( OPENPGL_SHOW_PRINT_OUTS) - std::cout << "fitRegion: "<< (m_isSurface? "surface":"volume") << "\tnGuidingRegions = " << nGuidingRegions << std::endl; +#if defined(OPENPGL_SHOW_PRINT_OUTS) + std::cout << "fitRegion: " << (m_isSurface ? "surface" : "volume") << "\tnGuidingRegions = " << nGuidingRegions << std::endl; #endif #ifdef USE_EMBREE_PARALLEL - embree::parallel_for(0,(int)nGuidingRegions, 1, [&] ( const embree::range& r ) { - for (size_t n=r.begin(); n &r) { + for (size_t n = r.begin(); n < r.end(); n++) #else - tbb::parallel_for( tbb::blocked_range(0,nGuidingRegions), [&](tbb::blocked_range r) - { - for (int n = r.begin(); n(0, nGuidingRegions), [&](tbb::blocked_range r) { + for (int n = r.begin(); n < r.end(); ++n) #endif - { - RegionStorageType ®ionStorage = m_regionStorageContainer[n]; - openpgl::Point3 sampleMean = regionStorage.first.sampleStatistics.mean; - if(regionStorage.second.size() > 0) { - if (m_deterministic) + RegionStorageType ®ionStorage = m_regionStorageContainer[n]; + openpgl::Point3 sampleMean = regionStorage.first.sampleStatistics.mean; + if (regionStorage.second.size() > 0) { - std::sort(samples.begin() + regionStorage.second.m_begin, samples.begin() + regionStorage.second.m_end, SampleDataLess); - } + if (m_deterministic) + { + std::sort(samples.begin() + regionStorage.second.m_begin, samples.begin() + regionStorage.second.m_end, SampleDataLess); + } - if(m_fitRegions) { - typename DirectionalDistributionFactory::FittingStatistics fittingStats; - m_distributionFactory.prepareSamples(samples.data() + regionStorage.second.m_begin, regionStorage.second.m_end - regionStorage.second.m_begin, regionStorage.first.sampleStatistics, m_distributionFactorySettings); - m_distributionFactory.fit(regionStorage.first.distribution, regionStorage.first.trainingStatistics, samples.data() + regionStorage.second.m_begin, regionStorage.second.m_end - regionStorage.second.m_begin, m_distributionFactorySettings, fittingStats); + if (m_fitRegions) + { + typename DirectionalDistributionFactory::FittingStatistics fittingStats; + m_distributionFactory.prepareSamples(samples.data() + regionStorage.second.m_begin, regionStorage.second.m_end - regionStorage.second.m_begin, + regionStorage.first.sampleStatistics, m_distributionFactorySettings); + m_distributionFactory.fit(regionStorage.first.distribution, regionStorage.first.trainingStatistics, samples.data() + regionStorage.second.m_begin, + regionStorage.second.m_end - regionStorage.second.m_begin, m_distributionFactorySettings, fittingStats); #ifdef OPENPGL_RADIANCE_CACHES - m_distributionFactory.updateFluenceEstimate(regionStorage.first.distribution, samples.data() + regionStorage.second.m_begin, regionStorage.second.m_end - regionStorage.second.m_begin, regionStorage.first.numZeroValueSamples, regionStorage.first.sampleStatistics); - regionStorage.first.outRadianceHist.update(samples.data() + regionStorage.second.m_begin, regionStorage.second.m_end - regionStorage.second.m_begin, zeroValueSamples.data() + regionStorage.second.m_is_begin, regionStorage.second.m_is_end - regionStorage.second.m_is_begin); + m_distributionFactory.updateFluenceEstimate(regionStorage.first.distribution, samples.data() + regionStorage.second.m_begin, + regionStorage.second.m_end - regionStorage.second.m_begin, regionStorage.first.numZeroValueSamples, + regionStorage.first.sampleStatistics); + regionStorage.first.outRadianceHist.update(samples.data() + regionStorage.second.m_begin, regionStorage.second.m_end - regionStorage.second.m_begin, + zeroValueSamples.data() + regionStorage.second.m_is_begin, + regionStorage.second.m_is_end - regionStorage.second.m_is_begin); #endif - // TODO: we should move setting the pivot to the factory - regionStorage.first.distribution._pivotPosition = sampleMean; - regionStorage.first.valid = regionStorage.first.distribution.isValid(); + // TODO: we should move setting the pivot to the factory + regionStorage.first.distribution._pivotPosition = sampleMean; + regionStorage.first.valid = regionStorage.first.distribution.isValid(); #ifdef OPENPGL_DEBUG_MODE - if(!regionStorage.first.valid) - std::cout << "!!!! " << (m_isSurface? "Surface":"Volume") << " regionStorage.first.valid !!! " << regionStorage.first.distribution.toString() << std::endl; + if (!regionStorage.first.valid) + std::cout << "!!!! " << (m_isSurface ? "Surface" : "Volume") << " regionStorage.first.valid !!! " << regionStorage.first.distribution.toString() + << std::endl; #endif - regionStorage.first.splitFlag = false; + regionStorage.first.splitFlag = false; + } } + else + { + regionStorage.first.valid = false; + regionStorage.first.splitFlag = false; + } + regionStorage.second.reset(); + OPENPGL_ASSERT(regionStorage.first.isValid()); } - else - { - regionStorage.first.valid = false; - regionStorage.first.splitFlag = false; - } - regionStorage.second.reset(); - OPENPGL_ASSERT(regionStorage.first.isValid()); - } }); m_initialized = true; OPENPGL_ASSERT(this->isValid()); } - void updateRegions(SampleContainerInternal& samples, ZeroValueSampleContainerInternal& zeroValueSamples) + void updateRegions(SampleContainerInternal &samples, ZeroValueSampleContainerInternal &zeroValueSamples) { size_t nGuidingRegions = m_regionStorageContainer.size(); -#if defined( OPENPGL_SHOW_PRINT_OUTS) - std::cout << "updateRegion: " << (m_isSurface? "surface":"volume") << "\tnGuidingRegions = " << nGuidingRegions << std::endl; +#if defined(OPENPGL_SHOW_PRINT_OUTS) + std::cout << "updateRegion: " << (m_isSurface ? "surface" : "volume") << "\tnGuidingRegions = " << nGuidingRegions << std::endl; #endif #ifdef USE_EMBREE_PARALLEL - embree::parallel_for(0,(int)nGuidingRegions, 1, [&] ( const embree::range& r ) { - for (size_t n=r.begin(); n &r) { + for (size_t n = r.begin(); n < r.end(); n++) #else - tbb::parallel_for( tbb::blocked_range(0,nGuidingRegions), [&](tbb::blocked_range r) - { - for (int n = r.begin(); n(0, nGuidingRegions), [&](tbb::blocked_range r) { + for (int n = r.begin(); n < r.end(); ++n) #endif - { - RegionStorageType ®ionStorage = m_regionStorageContainer[n]; - if (regionStorage.first.splitFlag) { - regionStorage.first.distribution.decay(this->m_decayOnSpatialSplit); - regionStorage.first.trainingStatistics.decay(this->m_decayOnSpatialSplit); + RegionStorageType ®ionStorage = m_regionStorageContainer[n]; + if (regionStorage.first.splitFlag) + { + regionStorage.first.distribution.decay(this->m_decayOnSpatialSplit); + regionStorage.first.trainingStatistics.decay(this->m_decayOnSpatialSplit); #ifdef OPENPGL_RADIANCE_CACHES - regionStorage.first.outRadianceHist.decay(this->m_decayOnSpatialSplit); + regionStorage.first.outRadianceHist.decay(this->m_decayOnSpatialSplit); #endif - regionStorage.first.splitFlag = false; - } + regionStorage.first.splitFlag = false; + } - openpgl::Point3 sampleMean = regionStorage.first.sampleStatistics.mean; - if(regionStorage.second.size() > 0) - { -#ifdef OPENPGL_DEBUG_MODE - RegionType oldRegion = regionStorage.first; -#endif - if (m_deterministic) + openpgl::Point3 sampleMean = regionStorage.first.sampleStatistics.mean; + if (regionStorage.second.size() > 0) { - std::sort(samples.begin() + regionStorage.second.m_begin, samples.begin() + regionStorage.second.m_end, SampleDataLess); - } +#ifdef OPENPGL_DEBUG_MODE + RegionType oldRegion = regionStorage.first; +#endif + if (m_deterministic) + { + std::sort(samples.begin() + regionStorage.second.m_begin, samples.begin() + regionStorage.second.m_end, SampleDataLess); + } - if (m_fitRegions) { - // TODO: we should move applying the paralax comp to the Distribution to the factory - if(DirectionalDistribution::ParallaxCompensation == 1) - { - regionStorage.first.trainingStatistics.sufficientStatistics.applyParallaxShift(regionStorage.first.distribution, regionStorage.first.distribution._pivotPosition - sampleMean); - regionStorage.first.distribution.performRelativeParallaxShift(regionStorage.first.distribution._pivotPosition - sampleMean); - OPENPGL_ASSERT(regionStorage.first.distribution.isValid()); - OPENPGL_ASSERT(regionStorage.first.trainingStatistics.sufficientStatistics.isValid()); - } - typename DirectionalDistributionFactory::FittingStatistics fittingStats; - m_distributionFactory.prepareSamples(samples.data() + regionStorage.second.m_begin, regionStorage.second.m_end - regionStorage.second.m_begin, regionStorage.first.sampleStatistics, m_distributionFactorySettings); - m_distributionFactory.update(regionStorage.first.distribution, regionStorage.first.trainingStatistics, samples.data() + regionStorage.second.m_begin, regionStorage.second.m_end - regionStorage.second.m_begin, m_distributionFactorySettings, fittingStats); + if (m_fitRegions) + { + // TODO: we should move applying the paralax comp to the Distribution to the factory + if (DirectionalDistribution::ParallaxCompensation == 1) + { + regionStorage.first.trainingStatistics.sufficientStatistics.applyParallaxShift(regionStorage.first.distribution, + regionStorage.first.distribution._pivotPosition - sampleMean); + regionStorage.first.distribution.performRelativeParallaxShift(regionStorage.first.distribution._pivotPosition - sampleMean); + OPENPGL_ASSERT(regionStorage.first.distribution.isValid()); + OPENPGL_ASSERT(regionStorage.first.trainingStatistics.sufficientStatistics.isValid()); + } + typename DirectionalDistributionFactory::FittingStatistics fittingStats; + m_distributionFactory.prepareSamples(samples.data() + regionStorage.second.m_begin, regionStorage.second.m_end - regionStorage.second.m_begin, + regionStorage.first.sampleStatistics, m_distributionFactorySettings); + m_distributionFactory.update(regionStorage.first.distribution, regionStorage.first.trainingStatistics, samples.data() + regionStorage.second.m_begin, + regionStorage.second.m_end - regionStorage.second.m_begin, m_distributionFactorySettings, fittingStats); #ifdef OPENPGL_RADIANCE_CACHES - m_distributionFactory.updateFluenceEstimate(regionStorage.first.distribution, samples.data() + regionStorage.second.m_begin, regionStorage.second.m_end - regionStorage.second.m_begin, regionStorage.first.numZeroValueSamples, regionStorage.first.sampleStatistics); - regionStorage.first.outRadianceHist.update(samples.data() + regionStorage.second.m_begin, regionStorage.second.m_end - regionStorage.second.m_begin, zeroValueSamples.data() + regionStorage.second.m_is_begin, regionStorage.second.m_is_end - regionStorage.second.m_is_begin); + m_distributionFactory.updateFluenceEstimate(regionStorage.first.distribution, samples.data() + regionStorage.second.m_begin, + regionStorage.second.m_end - regionStorage.second.m_begin, regionStorage.first.numZeroValueSamples, + regionStorage.first.sampleStatistics); + regionStorage.first.outRadianceHist.update(samples.data() + regionStorage.second.m_begin, regionStorage.second.m_end - regionStorage.second.m_begin, + zeroValueSamples.data() + regionStorage.second.m_is_begin, + regionStorage.second.m_is_end - regionStorage.second.m_is_begin); #endif - regionStorage.first.valid = regionStorage.first.isValid(); + regionStorage.first.valid = regionStorage.first.isValid(); #ifdef OPENPGL_DEBUG_MODE - if(!regionStorage.first.valid) - { - std::cout << "!!!! " << (m_isSurface? "Surface":"Volume") << " regionStorage.first.valid !!! " << regionStorage.first.distribution.toString() << std::endl; - storeInvalidRegionData("regionBeforeUpdate_"+ std::string((m_isSurface? "surf":"vol")) + "_itr" + std::to_string(this->m_iteration) + "_region" + std::to_string(n)+".dump", oldRegion, dataPoints, m_distributionFactorySettings); - } + if (!regionStorage.first.valid) + { + std::cout << "!!!! " << (m_isSurface ? "Surface" : "Volume") << " regionStorage.first.valid !!! " << regionStorage.first.distribution.toString() + << std::endl; + storeInvalidRegionData("regionBeforeUpdate_" + std::string((m_isSurface ? "surf" : "vol")) + "_itr" + std::to_string(this->m_iteration) + "_region" + + std::to_string(n) + ".dump", + oldRegion, dataPoints, m_distributionFactorySettings); + } #endif + } } - } - else - { - RegionStorageType ®ionStorage = m_regionStorageContainer[n]; - if (regionStorage.first.splitFlag) + else { - regionStorage.first.trainingStatistics.decay(this->m_decayOnSpatialSplit); - regionStorage.first.splitFlag = false; + RegionStorageType ®ionStorage = m_regionStorageContainer[n]; + if (regionStorage.first.splitFlag) + { + regionStorage.first.trainingStatistics.decay(this->m_decayOnSpatialSplit); + regionStorage.first.splitFlag = false; + } } + regionStorage.second.reset(); + OPENPGL_ASSERT(regionStorage.first.isValid()); } - regionStorage.second.reset(); - OPENPGL_ASSERT(regionStorage.first.isValid()); - } }); OPENPGL_ASSERT(this->isValid()); } - static void storeInvalidRegionData(const std::string &fileName, const RegionType ®ionBeforeUpdate, const std::vector &samples, const DirectionalDistributionFactorySettings &factorySettings) + static void storeInvalidRegionData(const std::string &fileName, const RegionType ®ionBeforeUpdate, const std::vector &samples, + const DirectionalDistributionFactorySettings &factorySettings) { std::filebuf fbDump; - fbDump.open (fileName,std::ios::out); + fbDump.open(fileName, std::ios::out); std::ostream dumpStream(&fbDump); factorySettings.serialize(dumpStream); size_t numSamples = samples.size(); - dumpStream.write(reinterpret_cast(&numSamples), sizeof(size_t)); + dumpStream.write(reinterpret_cast(&numSamples), sizeof(size_t)); for (size_t i = 0; i < numSamples; i++) { - dumpStream.write(reinterpret_cast(&samples[i]), sizeof(openpgl::SampleData)); + dumpStream.write(reinterpret_cast(&samples[i]), sizeof(openpgl::SampleData)); } regionBeforeUpdate.serialize(dumpStream); fbDump.close(); } -public: - static void loadInvalidRegionData(const std::string &fileName, RegionType ®ionBeforeUpdate, std::vector &samples, DirectionalDistributionFactorySettings &factorySettings) + + public: + static void loadInvalidRegionData(const std::string &fileName, RegionType ®ionBeforeUpdate, std::vector &samples, + DirectionalDistributionFactorySettings &factorySettings) { std::filebuf fbDumpIn; - fbDumpIn.open (fileName,std::ios::in); + fbDumpIn.open(fileName, std::ios::in); std::istream dumpIStream(&fbDumpIn); factorySettings.deserialize(dumpIStream); samples.clear(); size_t numSamples; - dumpIStream.read(reinterpret_cast(&numSamples), sizeof(size_t)); + dumpIStream.read(reinterpret_cast(&numSamples), sizeof(size_t)); for (size_t i = 0; i < numSamples; i++) { SampleData dsd; - dumpIStream.read(reinterpret_cast(&dsd), sizeof(openpgl::SampleData)); + dumpIStream.read(reinterpret_cast(&dsd), sizeof(openpgl::SampleData)); samples.push_back(dsd); } regionBeforeUpdate.deserialize(dumpIStream); fbDumpIn.close(); } - bool operator==(const Field& b) const { + bool operator==(const Field &b) const + { bool equal = true; - if(!m_initialized && !b.m_initialized) + if (!m_initialized && !b.m_initialized) return true; - if(m_isSurface != b.m_isSurface || m_decayOnSpatialSplit != b.m_decayOnSpatialSplit || - m_iteration != b.m_iteration || m_totalSPP != b.m_totalSPP || - /*m_numThreads != b.m_numThreads ||*/ m_deterministic != b.m_deterministic || m_fitRegions != b.m_fitRegions || - m_isSceneBoundsSet != b.m_isSceneBoundsSet || m_sceneBounds.lower.x != b.m_sceneBounds.lower.x || - m_sceneBounds.lower.y != b.m_sceneBounds.lower.y || m_sceneBounds.lower.z != b.m_sceneBounds.lower.z || - m_sceneBounds.upper.x != b.m_sceneBounds.upper.x || m_sceneBounds.upper.y != b.m_sceneBounds.upper.y || - m_sceneBounds.upper.z != b.m_sceneBounds.upper.z || m_initialized != b.m_initialized || - !m_distributionFactorySettings.operator==(b.m_distributionFactorySettings) || + if (m_isSurface != b.m_isSurface || m_decayOnSpatialSplit != b.m_decayOnSpatialSplit || m_iteration != b.m_iteration || m_totalSPP != b.m_totalSPP || + /*m_numThreads != b.m_numThreads ||*/ m_deterministic != b.m_deterministic || m_fitRegions != b.m_fitRegions || m_isSceneBoundsSet != b.m_isSceneBoundsSet || + m_sceneBounds.lower.x != b.m_sceneBounds.lower.x || m_sceneBounds.lower.y != b.m_sceneBounds.lower.y || m_sceneBounds.lower.z != b.m_sceneBounds.lower.z || + m_sceneBounds.upper.x != b.m_sceneBounds.upper.x || m_sceneBounds.upper.y != b.m_sceneBounds.upper.y || m_sceneBounds.upper.z != b.m_sceneBounds.upper.z || + m_initialized != b.m_initialized || !m_distributionFactorySettings.operator==(b.m_distributionFactorySettings) || !m_spatialSubdivBuilderSettings.operator==(b.m_spatialSubdivBuilderSettings) || - //!m_spatialSubdiv.operator==(b.m_spatialSubdiv) || + //! m_spatialSubdiv.operator==(b.m_spatialSubdiv) || m_useStochasticNNLookUp != b.m_useStochasticNNLookUp) { equal = false; } - std::vector< uint32_t > dataStorageIndicesA; + std::vector dataStorageIndicesA; std::vector treeNodesA; m_spatialSubdiv.rearrangeNodesForCompare(treeNodesA, dataStorageIndicesA); - std::vector< uint32_t > dataStorageIndicesB; + std::vector dataStorageIndicesB; std::vector treeNodesB; b.m_spatialSubdiv.rearrangeNodesForCompare(treeNodesB, dataStorageIndicesB); - if(dataStorageIndicesA.size() != dataStorageIndicesB.size() || - treeNodesA.size() != treeNodesB.size() || - m_regionStorageContainer.size() != b.m_regionStorageContainer.size()) { + if (dataStorageIndicesA.size() != dataStorageIndicesB.size() || treeNodesA.size() != treeNodesB.size() || + m_regionStorageContainer.size() != b.m_regionStorageContainer.size()) + { equal = false; return equal; } - for (int n = 0; n < treeNodesA.size(); n++) { - if(!treeNodesA[n].operator==(treeNodesB[n])){ + for (int n = 0; n < treeNodesA.size(); n++) + { + if (!treeNodesA[n].operator==(treeNodesB[n])) + { equal = false; } } - for (int n = 0; n < dataStorageIndicesA.size(); n++) { + for (int n = 0; n < dataStorageIndicesA.size(); n++) + { size_t idxA = dataStorageIndicesA[n]; size_t idxB = dataStorageIndicesB[n]; - if(!m_regionStorageContainer[idxA].second.operator==(b.m_regionStorageContainer[idxB].second) || - !m_regionStorageContainer[idxA].first.operator==(b.m_regionStorageContainer[idxB].first)){ + if (!m_regionStorageContainer[idxA].second.operator==(b.m_regionStorageContainer[idxB].second) || + !m_regionStorageContainer[idxA].first.operator==(b.m_regionStorageContainer[idxB].first)) + { equal = false; } } return equal; } - - FieldStatistics* getStatistics() const + FieldStatistics *getStatistics() const { - FieldStatistics* stats = new FieldStatistics(); + FieldStatistics *stats = new FieldStatistics(); stats->numCacheRegions = m_regionStorageContainer.size(); stats->numCacheRegionsReserved = m_regionStorageContainer.capacity(); stats->sizePerCacheRegions = sizeof(RegionStorageType); @@ -660,7 +681,7 @@ struct Field stats->timeLastUpdateCopySamples = m_timeLastUpdateCopySamples; stats->timeLastUpdateSpatialStructureUpdate = m_timeLastUpdateSpatialStructureUpdate; stats->timeLastUpdateDirectionalDistriubtionUpdate = m_timeLastUpdateDirectionalDistriubtionUpdate; - + stats->spatialStructureStatistics = m_spatialSubdiv.getStatistics(); stats->directionalDistributionStatistics.sizePerDistribution = sizeof(DirectionalDistribution); @@ -670,13 +691,15 @@ struct Field stats->directionalDistributionStatistics.secondMomentNumberOfComponents = 0.0f; int numDistributions = m_regionStorageContainer.size(); - for (int i=0; i < numDistributions; i++) + for (int i = 0; i < numDistributions; i++) { int numDistributionComponents = m_regionStorageContainer[i].first.distribution.getNumComponents(); - stats->directionalDistributionStatistics.minNumberOfComponents = std::min(stats->directionalDistributionStatistics.minNumberOfComponents, (float)numDistributionComponents); - stats->directionalDistributionStatistics.maxNumberOfComponents = std::max(stats->directionalDistributionStatistics.maxNumberOfComponents, (float)numDistributionComponents); + stats->directionalDistributionStatistics.minNumberOfComponents = + std::min(stats->directionalDistributionStatistics.minNumberOfComponents, (float)numDistributionComponents); + stats->directionalDistributionStatistics.maxNumberOfComponents = + std::max(stats->directionalDistributionStatistics.maxNumberOfComponents, (float)numDistributionComponents); stats->directionalDistributionStatistics.averageNumberOfComponents += numDistributionComponents; - stats->directionalDistributionStatistics.secondMomentNumberOfComponents += numDistributionComponents*numDistributionComponents; + stats->directionalDistributionStatistics.secondMomentNumberOfComponents += numDistributionComponents * numDistributionComponents; } stats->directionalDistributionStatistics.averageNumberOfComponents /= float(numDistributions); stats->directionalDistributionStatistics.secondMomentNumberOfComponents /= float(numDistributions); @@ -684,24 +707,23 @@ struct Field return stats; } -private: - + private: bool m_isSurface{true}; - float m_decayOnSpatialSplit {0.25f}; + float m_decayOnSpatialSplit{0.25f}; - size_t m_iteration {0}; - size_t m_totalSPP {0}; + size_t m_iteration{0}; + size_t m_totalSPP{0}; // flag to deactivate the training of the directional distributions (i.e., for benchmarking the spatial structure build) - bool m_fitRegions {true}; + bool m_fitRegions{true}; // if the fitting process should be deterministic (i.e, samples are sorted before training) - bool m_deterministic {false}; + bool m_deterministic{false}; bool m_isSceneBoundsSet{false}; BBox m_sceneBounds; - bool m_initialized {false}; + bool m_initialized{false}; DirectionalDistributionFactory m_distributionFactory; DirectionalDistributionFactorySettings m_distributionFactorySettings; @@ -715,17 +737,17 @@ struct Field SpatialStructure m_spatialSubdiv; RegionStorageContainerType m_regionStorageContainer; - bool m_useStochasticNNLookUp {false}; - bool m_useISNNLookUp {false}; + bool m_useStochasticNNLookUp{false}; + bool m_useISNNLookUp{false}; KNearestRegionsSearchTree m_regionKNNSearchTree; SampleContainerInternal samples_; ZeroValueSampleContainerInternal zeroValueSamples_; - float m_timeLastUpdate {0.f}; - float m_timeLastUpdateCopySamples {0.f}; - float m_timeLastUpdateSpatialStructureUpdate {0.f}; - float m_timeLastUpdateDirectionalDistriubtionUpdate {0.f}; + float m_timeLastUpdate{0.f}; + float m_timeLastUpdateCopySamples{0.f}; + float m_timeLastUpdateSpatialStructureUpdate{0.f}; + float m_timeLastUpdateDirectionalDistriubtionUpdate{0.f}; }; -} +} // namespace openpgl diff --git a/openpgl/field/FieldStatistics.h b/openpgl/field/FieldStatistics.h index a142f2e..534aff5 100644 --- a/openpgl/field/FieldStatistics.h +++ b/openpgl/field/FieldStatistics.h @@ -3,34 +3,36 @@ #pragma once +#include +#include + +#include "../directional/DirectionalDistributionStatistics.h" #include "../openpgl_common.h" #include "../spatial/kdtree/KDTreeStatistics.h" -#include "../directional/DirectionalDistributionStatistics.h" - -#include -#include namespace openpgl { -struct FieldStatistics{ +struct FieldStatistics +{ using SpatialStatistics = KDTreeStatistics; - size_t numCacheRegions {0}; - size_t numCacheRegionsReserved {0}; - size_t sizePerCacheRegions {0}; - size_t sizeAllCacheRegionsUsed {0}; - size_t sizeAllCacheRegionsReserved {0}; + size_t numCacheRegions{0}; + size_t numCacheRegionsReserved{0}; + size_t sizePerCacheRegions{0}; + size_t sizeAllCacheRegionsUsed{0}; + size_t sizeAllCacheRegionsReserved{0}; - float timeLastUpdate {0.f}; - float timeLastUpdateCopySamples {0.f}; - float timeLastUpdateSpatialStructureUpdate {0.f}; - float timeLastUpdateDirectionalDistriubtionUpdate {0.f}; + float timeLastUpdate{0.f}; + float timeLastUpdateCopySamples{0.f}; + float timeLastUpdateSpatialStructureUpdate{0.f}; + float timeLastUpdateDirectionalDistriubtionUpdate{0.f}; SpatialStatistics spatialStructureStatistics; DirectionalDistributionStatistics directionalDistributionStatistics; - std::string headerCSVString() const{ + std::string headerCSVString() const + { const std::string separator = " , "; std::stringstream ss; ss << "FieldStatistics:" << separator; @@ -51,15 +53,16 @@ struct FieldStatistics{ return ss.str(); } - std::string toCSVString() const{ + std::string toCSVString() const + { const std::string separator = " , "; std::stringstream ss; ss << " " << separator; ss << numCacheRegions << separator; ss << numCacheRegionsReserved << separator; ss << sizePerCacheRegions << separator; - ss << float(sizeAllCacheRegionsUsed) / 1024 / 1024 << separator; - ss << float(sizeAllCacheRegionsReserved) / 1024 / 1024 << separator; + ss << float(sizeAllCacheRegionsUsed) / 1024 / 1024 << separator; + ss << float(sizeAllCacheRegionsReserved) / 1024 / 1024 << separator; ss << timeLastUpdate << separator; ss << timeLastUpdateCopySamples << separator; @@ -72,16 +75,17 @@ struct FieldStatistics{ return ss.str(); } - std::string toString() const{ + std::string toString() const + { const std::string tab = "\t"; std::stringstream ss; ss << "FieldStatistics:" << std::endl; ss << tab << "numCacheRegions = " << numCacheRegions << std::endl; ss << tab << "numCacheRegionsReserved = " << numCacheRegionsReserved << std::endl; ss << tab << "sizePerCacheRegions = " << sizePerCacheRegions << " bs" << std::endl; - ss << tab << "sizeAllCacheRegionsUsed = " << float(sizeAllCacheRegionsUsed) / 1024 / 1024 << " Mbs" << std::endl; + ss << tab << "sizeAllCacheRegionsUsed = " << float(sizeAllCacheRegionsUsed) / 1024 / 1024 << " Mbs" << std::endl; ss << tab << "sizeAllCacheRegionsReserved = " << float(sizeAllCacheRegionsReserved) / 1024 / 1024 << " Mbs" << std::endl; - + ss << tab << "timeUpdate = " << timeLastUpdate << " ms" << std::endl; ss << tab << "timeCopySamples = " << timeLastUpdateCopySamples << " ms" << std::endl; ss << tab << "timeSpatialStructureUpdate = " << timeLastUpdateSpatialStructureUpdate << " ms" << std::endl; @@ -94,4 +98,4 @@ struct FieldStatistics{ } }; -} +} // namespace openpgl diff --git a/openpgl/field/ISurfaceVolumeField.h b/openpgl/field/ISurfaceVolumeField.h index 1940fdf..2788099 100644 --- a/openpgl/field/ISurfaceVolumeField.h +++ b/openpgl/field/ISurfaceVolumeField.h @@ -7,7 +7,6 @@ #include "../directional/ISurfaceSamplingDistribution.h" #include "../directional/IVolumeSamplingDistribution.h" - namespace openpgl { @@ -15,28 +14,27 @@ struct FieldStatistics; struct ISurfaceVolumeField { - using SampleContainer = SampleDataStorage::SampleContainer; virtual ~ISurfaceVolumeField(){}; - virtual ISurfaceSamplingDistribution* newSurfaceSamplingDistribution() const = 0; + virtual ISurfaceSamplingDistribution *newSurfaceSamplingDistribution() const = 0; - virtual bool initSurfaceSamplingDistribution(ISurfaceSamplingDistribution* surfaceSamplingDistribution, const Point3& position, float* sample1D) const = 0; + virtual bool initSurfaceSamplingDistribution(ISurfaceSamplingDistribution *surfaceSamplingDistribution, const Point3 &position, float *sample1D) const = 0; - virtual IVolumeSamplingDistribution* newVolumeSamplingDistribution() const = 0; + virtual IVolumeSamplingDistribution *newVolumeSamplingDistribution() const = 0; - virtual bool initVolumeSamplingDistribution(IVolumeSamplingDistribution* volumeSamplingDistribution, const Point3& position, float* sample1D) const = 0; + virtual bool initVolumeSamplingDistribution(IVolumeSamplingDistribution *volumeSamplingDistribution, const Point3 &position, float *sample1D) const = 0; virtual void setSceneBounds(const openpgl::BBox &sceneBounds) = 0; virtual openpgl::BBox getSceneBounds() const = 0; - virtual void updateField(SampleContainer& samplesSurface, SampleContainer& samplesVolume) = 0; + virtual void updateField(SampleContainer &samplesSurface, SampleContainer &samplesVolume) = 0; - virtual void updateFieldSurface(SampleContainer& samplesSurface) = 0; + virtual void updateFieldSurface(SampleContainer &samplesSurface) = 0; - virtual void updateFieldVolume(SampleContainer& samplesVolume) = 0; + virtual void updateFieldVolume(SampleContainer &samplesVolume) = 0; virtual void resetField() = 0; @@ -54,10 +52,10 @@ struct ISurfaceVolumeField virtual void storeToFile(const std::string fieldFileName) const = 0; - virtual bool operator==(const ISurfaceVolumeField* b) const = 0; + virtual bool operator==(const ISurfaceVolumeField *b) const = 0; - virtual FieldStatistics* getSurfaceStatistics() const = 0; + virtual FieldStatistics *getSurfaceStatistics() const = 0; - virtual FieldStatistics* getVolumeStatistics() const = 0; + virtual FieldStatistics *getVolumeStatistics() const = 0; }; -} +} // namespace openpgl diff --git a/openpgl/field/SurfaceVolumeField.h b/openpgl/field/SurfaceVolumeField.h index 06dd629..eb75957 100644 --- a/openpgl/field/SurfaceVolumeField.h +++ b/openpgl/field/SurfaceVolumeField.h @@ -3,80 +3,75 @@ #pragma once -#include "ISurfaceVolumeField.h" #include "Field.h" #include "FieldStatistics.h" +#include "ISurfaceVolumeField.h" #define FIELD_FILE_HEADER_STRING "OPENPGL_" OPENPGL_VERSION_STRING "_FIELD" namespace openpgl { - -template class TSpatialStructureBuilder, typename TSurfaceSamplingDistribution, typename TVolumeSamplingDistribution> -struct SurfaceVolumeField: public ISurfaceVolumeField +template class TSpatialStructureBuilder, typename TSurfaceSamplingDistribution, + typename TVolumeSamplingDistribution> +struct SurfaceVolumeField : public ISurfaceVolumeField { - -private: - + private: using FieldType = Field; using SampleContainer = SampleDataStorage::SampleContainer; -public: + public: using Settings = typename FieldType::Settings; using RegionType = typename FieldType::RegionType; using DirectionalDistribution = typename FieldType::DirectionalDistribution; -public: + public: SurfaceVolumeField() = default; - SurfaceVolumeField(const Settings &settings): - m_surfaceField(settings), - m_volumeField(settings) - { + SurfaceVolumeField(const Settings &settings) : m_surfaceField(settings), m_volumeField(settings) + { m_surfaceField.setIsSurface(true); m_volumeField.setIsSurface(false); } - ~SurfaceVolumeField() override - {} + ~SurfaceVolumeField() override {} - ISurfaceSamplingDistribution* newSurfaceSamplingDistribution() const override + ISurfaceSamplingDistribution *newSurfaceSamplingDistribution() const override { return new TSurfaceSamplingDistribution(); } - bool initSurfaceSamplingDistribution(ISurfaceSamplingDistribution* surfaceSamplingDistribution, const Point3& position, float* sample1D) const override + bool initSurfaceSamplingDistribution(ISurfaceSamplingDistribution *surfaceSamplingDistribution, const Point3 &position, float *sample1D) const override { - TSurfaceSamplingDistribution* _surfaceSamplingDistribution = (TSurfaceSamplingDistribution*)surfaceSamplingDistribution; + TSurfaceSamplingDistribution *_surfaceSamplingDistribution = (TSurfaceSamplingDistribution *)surfaceSamplingDistribution; uint32_t id = -1; - const RegionType* region = m_surfaceField.getRegion(position, sample1D, id); - if(!region || !region->valid) + const RegionType *region = m_surfaceField.getRegion(position, sample1D, id); + if (!region || !region->valid) { return false; } - const DirectionalDistribution* distribution = ®ion->distribution; + const DirectionalDistribution *distribution = ®ion->distribution; _surfaceSamplingDistribution->init(distribution, position); _surfaceSamplingDistribution->setId(id); _surfaceSamplingDistribution->setRegion(region); return true; } - IVolumeSamplingDistribution* newVolumeSamplingDistribution() const override + IVolumeSamplingDistribution *newVolumeSamplingDistribution() const override { return new TVolumeSamplingDistribution(); } - bool initVolumeSamplingDistribution(IVolumeSamplingDistribution* volumeSamplingDistribution, const Point3& position, float* sample1D) const override + bool initVolumeSamplingDistribution(IVolumeSamplingDistribution *volumeSamplingDistribution, const Point3 &position, float *sample1D) const override { - TVolumeSamplingDistribution* _volumeSamplingDistribution = (TVolumeSamplingDistribution*)volumeSamplingDistribution; + TVolumeSamplingDistribution *_volumeSamplingDistribution = (TVolumeSamplingDistribution *)volumeSamplingDistribution; uint32_t id = -1; - const RegionType* region = m_volumeField.getRegion(position, sample1D, id); - if(!region || !region->valid) + const RegionType *region = m_volumeField.getRegion(position, sample1D, id); + if (!region || !region->valid) { return false; } - const DirectionalDistribution* distribution = region->getDistribution(position); + const DirectionalDistribution *distribution = region->getDistribution(position); _volumeSamplingDistribution->init(distribution, position); _volumeSamplingDistribution->setId(id); _volumeSamplingDistribution->setRegion(region); @@ -98,48 +93,64 @@ struct SurfaceVolumeField: public ISurfaceVolumeField return sceneBounds; } - void updateField(SampleContainer& samplesSurface, SampleContainer& samplesVolume) override + void updateField(SampleContainer &samplesSurface, SampleContainer &samplesVolume) override { - #if TBB_INTERFACE_VERSION < 12010 +#if TBB_INTERFACE_VERSION < 12010 // we need to initialize the task_scheduler in the context to avoid // asyncronous deconsrution of the implicit initialized tbb::arenas and tbb::streams tbb::task_scheduler_init anonymous; - #endif - if(samplesSurface.samples.size() > 0) { - if(!m_surfaceField.isInitialized()) { +#endif + if (samplesSurface.samples.size() > 0) + { + if (!m_surfaceField.isInitialized()) + { m_surfaceField.buildField(samplesSurface); - } else { + } + else + { m_surfaceField.updateField(samplesSurface); } } - if(samplesVolume.samples.size() > 0) { - if(!m_volumeField.isInitialized()) { + if (samplesVolume.samples.size() > 0) + { + if (!m_volumeField.isInitialized()) + { m_volumeField.buildField(samplesVolume); - } else { + } + else + { m_volumeField.updateField(samplesVolume); } } m_iteration++; } - void updateFieldSurface(SampleContainer& samplesSurface) override + void updateFieldSurface(SampleContainer &samplesSurface) override { - if(samplesSurface.samples.size() > 0) { - if(!m_surfaceField.isInitialized()) { + if (samplesSurface.samples.size() > 0) + { + if (!m_surfaceField.isInitialized()) + { m_surfaceField.buildField(samplesSurface); - } else { + } + else + { m_surfaceField.updateField(samplesSurface); } } m_iteration++; } - void updateFieldVolume(SampleContainer& samplesVolume) override + void updateFieldVolume(SampleContainer &samplesVolume) override { - if(samplesVolume.samples.size() > 0) { - if(!m_volumeField.isInitialized()) { + if (samplesVolume.samples.size() > 0) + { + if (!m_volumeField.isInitialized()) + { m_volumeField.buildField(samplesVolume); - } else { + } + else + { m_volumeField.updateField(samplesVolume); } } @@ -154,11 +165,13 @@ struct SurfaceVolumeField: public ISurfaceVolumeField m_volumeField.resetField(); } - PGL_SPATIAL_STRUCTURE_TYPE getSpatialStructureType() const override { + PGL_SPATIAL_STRUCTURE_TYPE getSpatialStructureType() const override + { return FieldType::SpatialStructureBuilder::SPATIAL_STRUCTURE_TYPE; } - PGL_DIRECTIONAL_DISTRIBUTION_TYPE getDirectionalDistributionType() const override { + PGL_DIRECTIONAL_DISTRIBUTION_TYPE getDirectionalDistributionType() const override + { return FieldType::DirectionalDistributionFactory::DIRECTIONAL_DISTRIBUTION_TYPE; } @@ -169,16 +182,16 @@ struct SurfaceVolumeField: public ISurfaceVolumeField void serialize(std::ostream &os) const override { - os.write(reinterpret_cast(&m_iteration), sizeof(m_iteration)); - os.write(reinterpret_cast(&m_totalSPP), sizeof(m_totalSPP)); + os.write(reinterpret_cast(&m_iteration), sizeof(m_iteration)); + os.write(reinterpret_cast(&m_totalSPP), sizeof(m_totalSPP)); m_surfaceField.serialize(os); m_volumeField.serialize(os); } void deserialize(std::istream &is) override { - is.read(reinterpret_cast(&m_iteration), sizeof(m_iteration)); - is.read(reinterpret_cast(&m_totalSPP), sizeof(m_totalSPP)); + is.read(reinterpret_cast(&m_iteration), sizeof(m_iteration)); + is.read(reinterpret_cast(&m_totalSPP), sizeof(m_totalSPP)); m_surfaceField.deserialize(is); m_volumeField.deserialize(is); } @@ -186,25 +199,27 @@ struct SurfaceVolumeField: public ISurfaceVolumeField virtual bool validate(const bool checkSurface, const bool checkVolume) const override { bool valid = true; - if(m_surfaceField.isInitialized()) + if (m_surfaceField.isInitialized()) valid = valid & m_surfaceField.isValid(); - if(m_volumeField.isInitialized()) + if (m_volumeField.isInitialized()) valid = valid & m_volumeField.isValid(); return valid; } - void storeToFile(const std::string fieldFileName) const override { + void storeToFile(const std::string fieldFileName) const override + { std::filebuf fb; - fb.open (fieldFileName, std::ios::out | std::ios::binary); - if (!fb.is_open()) throw std::runtime_error("error: couldn't open file!"); + fb.open(fieldFileName, std::ios::out | std::ios::binary); + if (!fb.is_open()) + throw std::runtime_error("error: couldn't open file!"); std::ostream os(&fb); os.write(FIELD_FILE_HEADER_STRING, strlen(FIELD_FILE_HEADER_STRING) + 1); auto spatialStructureType = FieldType::SpatialStructureBuilder::SPATIAL_STRUCTURE_TYPE; - os.write(reinterpret_cast(&spatialStructureType), sizeof(spatialStructureType)); + os.write(reinterpret_cast(&spatialStructureType), sizeof(spatialStructureType)); auto directionalDistributionType = FieldType::DirectionalDistributionFactory::DIRECTIONAL_DISTRIBUTION_TYPE; - os.write(reinterpret_cast(&directionalDistributionType), sizeof(directionalDistributionType)); + os.write(reinterpret_cast(&directionalDistributionType), sizeof(directionalDistributionType)); serialize(os); @@ -212,36 +227,36 @@ struct SurfaceVolumeField: public ISurfaceVolumeField fb.close(); } - virtual bool operator==(const ISurfaceVolumeField* b) const override { + virtual bool operator==(const ISurfaceVolumeField *b) const override + { bool equal = true; - const SurfaceVolumeField* fieldB = dynamic_cast(b); - if (!fieldB || m_iteration != fieldB->m_iteration || - m_totalSPP != fieldB->m_totalSPP || - !m_surfaceField.operator==(fieldB->m_surfaceField) || - !m_volumeField.operator==(fieldB->m_volumeField)) { - equal = false; - } + const SurfaceVolumeField *fieldB = dynamic_cast(b); + if (!fieldB || m_iteration != fieldB->m_iteration || m_totalSPP != fieldB->m_totalSPP || !m_surfaceField.operator==(fieldB->m_surfaceField) || + !m_volumeField.operator==(fieldB->m_volumeField)) + { + equal = false; + } return equal; } - FieldStatistics* getSurfaceStatistics() const override + FieldStatistics *getSurfaceStatistics() const override { - FieldStatistics* stats = m_surfaceField.getStatistics(); + FieldStatistics *stats = m_surfaceField.getStatistics(); return stats; } - FieldStatistics* getVolumeStatistics() const override + FieldStatistics *getVolumeStatistics() const override { - FieldStatistics* stats = m_volumeField.getStatistics(); + FieldStatistics *stats = m_volumeField.getStatistics(); return stats; } - -private: - size_t m_iteration {0}; - size_t m_totalSPP {0}; - + + private: + size_t m_iteration{0}; + size_t m_totalSPP{0}; + FieldType m_surfaceField; FieldType m_volumeField; }; -} +} // namespace openpgl diff --git a/openpgl/imagespace/Denoiser.h b/openpgl/imagespace/Denoiser.h index 36a0583..c3fc4c7 100644 --- a/openpgl/imagespace/Denoiser.h +++ b/openpgl/imagespace/Denoiser.h @@ -3,16 +3,16 @@ #pragma once -#include "../openpgl_common.h" - #include +#include "../openpgl_common.h" + namespace openpgl { -struct Denoiser{ - - Denoiser(pgl_point2i resolution, bool filterFeatures): m_resolution(resolution), m_filterFeatures(filterFeatures) +struct Denoiser +{ + Denoiser(pgl_point2i resolution, bool filterFeatures) : m_resolution(resolution), m_filterFeatures(filterFeatures) { oidnDevice = oidn::newDevice(); oidnDevice.commit(); @@ -21,15 +21,16 @@ struct Denoiser{ bufferColor3f = oidnDevice.newBuffer(numPixels * 3 * sizeof(float)); bufferScalar = oidnDevice.newBuffer(numPixels * 1 * sizeof(float)); - bufferAlbedo = oidnDevice.newBuffer(numPixels * 3 * sizeof(float)); + bufferAlbedo = oidnDevice.newBuffer(numPixels * 3 * sizeof(float)); bufferNormal = oidnDevice.newBuffer(numPixels * 3 * sizeof(float)); - - if (filterFeatures) { + + if (filterFeatures) + { oidnAlbedoFilter = oidnDevice.newFilter("RT"); oidnAlbedoFilter.setImage("albedo", bufferAlbedo, oidn::Format::Float3, m_resolution.x, m_resolution.y); oidnAlbedoFilter.setImage("output", bufferAlbedo, oidn::Format::Float3, m_resolution.x, m_resolution.y); oidnAlbedoFilter.commit(); - + oidnNormalFilter = oidnDevice.newFilter("RT"); oidnNormalFilter.setImage("normal", bufferNormal, oidn::Format::Float3, m_resolution.x, m_resolution.y); oidnNormalFilter.setImage("output", bufferNormal, oidn::Format::Float3, m_resolution.x, m_resolution.y); @@ -40,10 +41,12 @@ struct Denoiser{ oidnColor3fFilter.setImage("albedo", bufferAlbedo, oidn::Format::Float3, m_resolution.x, m_resolution.y); oidnColor3fFilter.setImage("normal", bufferNormal, oidn::Format::Float3, m_resolution.x, m_resolution.y); oidnColor3fFilter.setImage("output", bufferColor3f, oidn::Format::Float3, m_resolution.x, m_resolution.y); - oidnColor3fFilter.set("cleanAux", true); // auxiliary images will be prefiltered + oidnColor3fFilter.set("cleanAux", true); // auxiliary images will be prefiltered oidnColor3fFilter.set("hdr", true); oidnColor3fFilter.commit(); - } else { + } + else + { oidnColor3fFilter = oidnDevice.newFilter("RT"); oidnColor3fFilter.setImage("color", bufferColor3f, oidn::Format::Float3, m_resolution.x, m_resolution.y); oidnColor3fFilter.setImage("albedo", bufferAlbedo, oidn::Format::Float3, m_resolution.x, m_resolution.y); @@ -65,48 +68,50 @@ struct Denoiser{ { const std::size_t numPixels = m_resolution.x * m_resolution.y; // Copy data to OIDN buffers - bufferColor3f.write(0, numPixels*3*sizeof(float), rgb); - bufferNormal.write(0, numPixels*3*sizeof(float), n); - bufferAlbedo.write(0, numPixels*3*sizeof(float), albedo); - if (m_filterFeatures){ + bufferColor3f.write(0, numPixels * 3 * sizeof(float), rgb); + bufferNormal.write(0, numPixels * 3 * sizeof(float), n); + bufferAlbedo.write(0, numPixels * 3 * sizeof(float), albedo); + if (m_filterFeatures) + { oidnAlbedoFilter.execute(); oidnNormalFilter.execute(); } oidnColor3fFilter.execute(); - bufferColor3f.read(0, numPixels*3*sizeof(float), result); + bufferColor3f.read(0, numPixels * 3 * sizeof(float), result); } void denoise(pgl_vec3f *rgb, pgl_vec3f *rgb2nd, pgl_vec3f *n, pgl_vec3f *albedo, pgl_vec3f *result, pgl_vec3f *result2nd) { const std::size_t numPixels = m_resolution.x * m_resolution.y; // Copy data to OIDN buffers - bufferColor3f.write(0, numPixels*3*sizeof(float), rgb); - bufferNormal.write(0, numPixels*3*sizeof(float), n); - bufferAlbedo.write(0, numPixels*3*sizeof(float), albedo); - if (m_filterFeatures){ + bufferColor3f.write(0, numPixels * 3 * sizeof(float), rgb); + bufferNormal.write(0, numPixels * 3 * sizeof(float), n); + bufferAlbedo.write(0, numPixels * 3 * sizeof(float), albedo); + if (m_filterFeatures) + { oidnAlbedoFilter.execute(); oidnNormalFilter.execute(); } oidnColor3fFilter.execute(); - bufferColor3f.read(0, numPixels*3*sizeof(float), result); + bufferColor3f.read(0, numPixels * 3 * sizeof(float), result); - bufferColor3f.write(0, numPixels*3*sizeof(float), rgb2nd); + bufferColor3f.write(0, numPixels * 3 * sizeof(float), rgb2nd); oidnColor3fFilter.execute(); - bufferColor3f.read(0, numPixels*3*sizeof(float), result2nd); + bufferColor3f.read(0, numPixels * 3 * sizeof(float), result2nd); } void denoise(float *l, float *result) { const std::size_t numPixels = m_resolution.x * m_resolution.y; - bufferScalar.write(0, numPixels*1*sizeof(float), l); - oidnScalarFilter.execute(); - bufferScalar.read(0, numPixels*1*sizeof(float), result); + bufferScalar.write(0, numPixels * 1 * sizeof(float), l); + oidnScalarFilter.execute(); + bufferScalar.read(0, numPixels * 1 * sizeof(float), result); } - private: + private: pgl_point2i m_resolution; - bool m_filterFeatures {false}; + bool m_filterFeatures{false}; oidn::DeviceRef oidnDevice; oidn::FilterRef oidnColor3fFilter; @@ -120,4 +125,4 @@ struct Denoiser{ oidn::BufferRef bufferNormal; }; -} \ No newline at end of file +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/imagespace/ImageSpaceGuidingBuffer.h b/openpgl/imagespace/ImageSpaceGuidingBuffer.h index 1dcdd5b..65f4c5c 100644 --- a/openpgl/imagespace/ImageSpaceGuidingBuffer.h +++ b/openpgl/imagespace/ImageSpaceGuidingBuffer.h @@ -4,7 +4,6 @@ #pragma once #include "../openpgl_common.h" - #include "Denoiser.h" #ifdef USE_EMBREE_PARALLEL @@ -14,26 +13,26 @@ #include #endif -//Please include your own zlib-compatible API header before -//including `tinyexr.h` when you disable `TINYEXR_USE_MINIZ` +// Please include your own zlib-compatible API header before +// including `tinyexr.h` when you disable `TINYEXR_USE_MINIZ` #define TINYEXR_USE_MINIZ 0 #define TINYEXR_USE_NANOZLIB 1 -//#include "zlib.h" -//Or, if your project uses `stb_image[_write].h`, use their -//zlib implementation: -//#define TINYEXR_USE_STB_ZLIB 1 -//#define TINYEXR_USE_THREAD 1 +// #include "zlib.h" +// Or, if your project uses `stb_image[_write].h`, use their +// zlib implementation: +// #define TINYEXR_USE_STB_ZLIB 1 +// #define TINYEXR_USE_THREAD 1 #define TINYEXR_IMPLEMENTATION #include - namespace openpgl { -struct ImageSpaceGuidingBuffer{ - - struct Buffers { - Buffers(pgl_point2i resolution): numPixels(resolution.x*resolution.y) +struct ImageSpaceGuidingBuffer +{ + struct Buffers + { + Buffers(pgl_point2i resolution) : numPixels(resolution.x * resolution.y) { contribution = new pgl_vec3f[numPixels]; secondMoment = new pgl_vec3f[numPixels]; @@ -44,8 +43,8 @@ struct ImageSpaceGuidingBuffer{ filteredContribution = new pgl_vec3f[numPixels]; filteredSecondMoment = new pgl_vec3f[numPixels]; - } - + } + ~Buffers() { delete[] contribution; @@ -61,50 +60,48 @@ struct ImageSpaceGuidingBuffer{ void reset() { - #ifdef USE_EMBREE_PARALLEL - embree::parallel_for(0,(int)numPixels, 1, [&] ( const embree::range& r ) { - for (size_t pIdx=r.begin(); pIdx &r) { + for (size_t pIdx = r.begin(); pIdx < r.end(); pIdx++) #else - tbb::parallel_for( tbb::blocked_range(0,numPixels), [&](tbb::blocked_range r) - { - for (int pIdx = r.begin(); pIdx(0, numPixels), [&](tbb::blocked_range r) { + for (int pIdx = r.begin(); pIdx < r.end(); ++pIdx) #endif - { - contribution[pIdx] = {0.f, 0.f, 0.f}; - secondMoment[pIdx] = {0.f, 0.f, 0.f}; + { + contribution[pIdx] = {0.f, 0.f, 0.f}; + secondMoment[pIdx] = {0.f, 0.f, 0.f}; - albedo[pIdx] = {0.f, 0.f, 0.f}; - normal[pIdx] = {0.f, 0.f, 0.f}; - spp[pIdx] = 0.f; + albedo[pIdx] = {0.f, 0.f, 0.f}; + normal[pIdx] = {0.f, 0.f, 0.f}; + spp[pIdx] = 0.f; - filteredContribution[pIdx] = {0.f, 0.f, 0.f}; - filteredSecondMoment[pIdx] = {0.f, 0.f, 0.f}; - } + filteredContribution[pIdx] = {0.f, 0.f, 0.f}; + filteredSecondMoment[pIdx] = {0.f, 0.f, 0.f}; + } }); } - int numPixels {0}; + int numPixels{0}; - pgl_vec3f* contribution {nullptr}; - pgl_vec3f* secondMoment {nullptr}; + pgl_vec3f *contribution{nullptr}; + pgl_vec3f *secondMoment{nullptr}; - pgl_vec3f* albedo {nullptr}; - pgl_vec3f* normal {nullptr}; - float* spp {nullptr}; + pgl_vec3f *albedo{nullptr}; + pgl_vec3f *normal{nullptr}; + float *spp{nullptr}; - pgl_vec3f* filteredContribution {nullptr}; - pgl_vec3f* filteredSecondMoment {nullptr}; + pgl_vec3f *filteredContribution{nullptr}; + pgl_vec3f *filteredSecondMoment{nullptr}; }; - ImageSpaceGuidingBuffer(pgl_point2i resolution, bool useSecondMoment): m_useSecondMoment(useSecondMoment), m_resolution(resolution) + ImageSpaceGuidingBuffer(pgl_point2i resolution, bool useSecondMoment) : m_useSecondMoment(useSecondMoment), m_resolution(resolution) { m_denoiser = new Denoiser(m_resolution, false); m_contributionEstimateBuffers = new Buffers(m_resolution); m_ready = false; } - ImageSpaceGuidingBuffer(const std::string& fileName) + ImageSpaceGuidingBuffer(const std::string &fileName) { EXRVersion exrVersion; EXRHeader exrHeader; @@ -112,13 +109,13 @@ struct ImageSpaceGuidingBuffer{ InitEXRHeader(&exrHeader); InitEXRImage(&exrImage); - + if (IsEXR(fileName.c_str()) == TINYEXR_SUCCESS) { m_ready = true; - + ParseEXRVersionFromFile(&exrVersion, fileName.c_str()); - ParseEXRHeaderFromFile(&exrHeader, &exrVersion,fileName.c_str(),nullptr); + ParseEXRHeaderFromFile(&exrHeader, &exrVersion, fileName.c_str(), nullptr); LoadEXRImageFromFile(&exrImage, &exrHeader, fileName.c_str(), nullptr); m_resolution.x = exrImage.width; @@ -132,108 +129,111 @@ struct ImageSpaceGuidingBuffer{ std::vector layer_names; tinyexr::GetLayers(exrHeader, layer_names); - for (int i = 0; i< layer_names.size(); i++) + for (int i = 0; i < layer_names.size(); i++) { std::string layerName = layer_names[i]; std::vector channels; - tinyexr::ChannelsInLayer( - exrHeader, layerName, channels); + tinyexr::ChannelsInLayer(exrHeader, layerName, channels); int nChannels = channels.size(); int idxR = -1; int idxG = -1; int idxB = -1; - //int idxA = -1; + // int idxA = -1; int idxY = -1; - for ( int j = 0; j < nChannels; j++) + for (int j = 0; j < nChannels; j++) { const tinyexr::LayerChannel &ch = channels[j]; - if (ch.name == "R") { + if (ch.name == "R") + { idxR = int(ch.index); - } else if (ch.name == "G") { + } + else if (ch.name == "G") + { idxG = int(ch.index); - } else if (ch.name == "B") { + } + else if (ch.name == "B") + { idxB = int(ch.index); - //} else if (ch.name == "A") { - // idxA = int(ch.index); - } else if (ch.name == "Y") { + //} else if (ch.name == "A") { + // idxA = int(ch.index); + } + else if (ch.name == "Y") + { idxY = int(ch.index); } } - - float* bufferPtr = nullptr; - if(layerName == "Contrib"){ - bufferPtr = (float*) m_contributionEstimateBuffers->filteredContribution; + float *bufferPtr = nullptr; + if (layerName == "Contrib") + { + bufferPtr = (float *)m_contributionEstimateBuffers->filteredContribution; } - else if(layerName == "Contribt2nd") + else if (layerName == "Contribt2nd") { - bufferPtr = (float*) m_contributionEstimateBuffers->filteredSecondMoment; + bufferPtr = (float *)m_contributionEstimateBuffers->filteredSecondMoment; } - else if(layerName == "Spp") + else if (layerName == "Spp") { - bufferPtr = (float*) m_contributionEstimateBuffers->spp; + bufferPtr = (float *)m_contributionEstimateBuffers->spp; } - else if(layerName == "ContribRaw") + else if (layerName == "ContribRaw") { - bufferPtr = (float*) m_contributionEstimateBuffers->contribution; + bufferPtr = (float *)m_contributionEstimateBuffers->contribution; } - else if(layerName == "Contribt2ndRaw") + else if (layerName == "Contribt2ndRaw") { - bufferPtr = (float*) m_contributionEstimateBuffers->secondMoment; + bufferPtr = (float *)m_contributionEstimateBuffers->secondMoment; } - else if(layerName == "Albedo") + else if (layerName == "Albedo") { - bufferPtr = (float*) m_contributionEstimateBuffers->albedo; + bufferPtr = (float *)m_contributionEstimateBuffers->albedo; } - else if(layerName == "N") + else if (layerName == "N") { - bufferPtr = (float*) m_contributionEstimateBuffers->normal; + bufferPtr = (float *)m_contributionEstimateBuffers->normal; } else { - } #ifdef USE_EMBREE_PARALLEL - embree::parallel_for(0,(int)numPixels, 1, [&] ( const embree::range& r ) { - for (size_t pIdx=r.begin(); pIdx &r) { + for (size_t pIdx = r.begin(); pIdx < r.end(); pIdx++) #else - tbb::parallel_for( tbb::blocked_range(0,numPixels), [&](tbb::blocked_range r) - { - for (int pIdx = r.begin(); pIdx(0, numPixels), [&](tbb::blocked_range r) { + for (int pIdx = r.begin(); pIdx < r.end(); ++pIdx) #endif - { - switch(nChannels){ - case 1: { - const float val = - reinterpret_cast(exrImage.images)[idxY][pIdx]; - - bufferPtr[pIdx*nChannels + 0] = val; - break; - } - case 3: { - const float valR = - reinterpret_cast(exrImage.images)[idxR][pIdx]; - const float valG = - reinterpret_cast(exrImage.images)[idxG][pIdx]; - const float valB = - reinterpret_cast(exrImage.images)[idxB][pIdx]; - - bufferPtr[pIdx*nChannels + 0] = valR; - bufferPtr[pIdx*nChannels + 1] = valG; - bufferPtr[pIdx*nChannels + 2] = valB; - break; + { + switch (nChannels) + { + case 1: + { + const float val = reinterpret_cast(exrImage.images)[idxY][pIdx]; + + bufferPtr[pIdx * nChannels + 0] = val; + break; + } + case 3: + { + const float valR = reinterpret_cast(exrImage.images)[idxR][pIdx]; + const float valG = reinterpret_cast(exrImage.images)[idxG][pIdx]; + const float valB = reinterpret_cast(exrImage.images)[idxB][pIdx]; + + bufferPtr[pIdx * nChannels + 0] = valR; + bufferPtr[pIdx * nChannels + 1] = valG; + bufferPtr[pIdx * nChannels + 2] = valB; + break; + } } } - } }); } m_ready = true; - } - else + } + else { m_ready = false; } @@ -245,7 +245,7 @@ struct ImageSpaceGuidingBuffer{ delete m_contributionEstimateBuffers; } - void store(const std::string& fileName) const + void store(const std::string &fileName) const { EXRHeader exrHeader; EXRImage exrImage; @@ -258,41 +258,41 @@ struct ImageSpaceGuidingBuffer{ std::vector numChannels; std::vector layerChannels; - std::vector channelValues; + std::vector channelValues; int cIdx = layerChannels.size(); - layerChannels.emplace_back(cIdx,"Contrib"); + layerChannels.emplace_back(cIdx, "Contrib"); numChannels.emplace_back(3); - channelValues.emplace_back((const float*)m_contributionEstimateBuffers->filteredContribution); + channelValues.emplace_back((const float *)m_contributionEstimateBuffers->filteredContribution); cIdx = layerChannels.size(); - layerChannels.emplace_back(cIdx,"Contribt2nd"); + layerChannels.emplace_back(cIdx, "Contribt2nd"); numChannels.emplace_back(3); - channelValues.emplace_back((const float*)m_contributionEstimateBuffers->filteredSecondMoment); + channelValues.emplace_back((const float *)m_contributionEstimateBuffers->filteredSecondMoment); cIdx = layerChannels.size(); - layerChannels.emplace_back(cIdx,"Spp"); + layerChannels.emplace_back(cIdx, "Spp"); numChannels.emplace_back(1); - channelValues.emplace_back((const float*)m_contributionEstimateBuffers->spp); + channelValues.emplace_back((const float *)m_contributionEstimateBuffers->spp); cIdx = layerChannels.size(); - layerChannels.emplace_back(cIdx,"ContribRaw"); + layerChannels.emplace_back(cIdx, "ContribRaw"); numChannels.emplace_back(3); - channelValues.emplace_back((const float*)m_contributionEstimateBuffers->contribution); + channelValues.emplace_back((const float *)m_contributionEstimateBuffers->contribution); cIdx = layerChannels.size(); - layerChannels.emplace_back(cIdx,"Contribt2ndRaw"); + layerChannels.emplace_back(cIdx, "Contribt2ndRaw"); numChannels.emplace_back(3); - channelValues.emplace_back((const float*)m_contributionEstimateBuffers->secondMoment); + channelValues.emplace_back((const float *)m_contributionEstimateBuffers->secondMoment); cIdx = layerChannels.size(); - layerChannels.emplace_back(cIdx,"Albedo"); + layerChannels.emplace_back(cIdx, "Albedo"); numChannels.emplace_back(3); - channelValues.emplace_back((const float*)m_contributionEstimateBuffers->albedo); + channelValues.emplace_back((const float *)m_contributionEstimateBuffers->albedo); cIdx = layerChannels.size(); - layerChannels.emplace_back(cIdx,"N"); + layerChannels.emplace_back(cIdx, "N"); numChannels.emplace_back(3); - channelValues.emplace_back((const float*)m_contributionEstimateBuffers->normal); + channelValues.emplace_back((const float *)m_contributionEstimateBuffers->normal); int totalNumLayers = layerChannels.size(); int totalNumChannels = 0; @@ -312,49 +312,55 @@ struct ImageSpaceGuidingBuffer{ std::vector> channelImages; for (int i = 0; i < totalNumLayers; i++) { - for(int j=0; j< numChannels[i]; j++) + for (int j = 0; j < numChannels[i]; j++) { channelImages.emplace_back(width * height); } int offset = channelImages.size() - numChannels[i]; #ifdef USE_EMBREE_PARALLEL - embree::parallel_for(0,(int)numPixels, 1, [&] ( const embree::range& r ) { - for (size_t pIdx=r.begin(); pIdx &r) { + for (size_t pIdx = r.begin(); pIdx < r.end(); pIdx++) #else - tbb::parallel_for( tbb::blocked_range(0,numPixels), [&](tbb::blocked_range r) - { - for (int pIdx = r.begin(); pIdx(0, numPixels), [&](tbb::blocked_range r) { + for (int pIdx = r.begin(); pIdx < r.end(); ++pIdx) #endif - { - for(int c = 0; c < numChannels[i]; c++) { - channelImages[offset+c][pIdx] = channelValues[i][(pIdx)*numChannels[i] + c]; + for (int c = 0; c < numChannels[i]; c++) + { + channelImages[offset + c][pIdx] = channelValues[i][(pIdx)*numChannels[i] + c]; + } } - } }); } // Set the channel names std::vector channels(totalNumChannels); int offset = 0; - for (int lay = 0; lay < totalNumLayers; ++lay) { + for (int lay = 0; lay < totalNumLayers; ++lay) + { char namePrefix[256]; std::size_t prefixLen = 0; - const char* layerName = layerChannels[lay].name.c_str(); - if (!layerName || layerName[0] == 0) { + const char *layerName = layerChannels[lay].name.c_str(); + if (!layerName || layerName[0] == 0) + { prefixLen = 0; namePrefix[0] = 0; - } else { + } + else + { prefixLen = strlen(layerName) + 1; strncpy(namePrefix, layerName, 255); namePrefix[prefixLen - 1] = '.'; } - if (numChannels[lay] == 1) { + if (numChannels[lay] == 1) + { strncpy(channels[offset + 0].name, namePrefix, 255); strncpy(channels[offset + 0].name + prefixLen, "Y", 255 - prefixLen); - } else if (numChannels[lay] == 3) { + } + else if (numChannels[lay] == 3) + { strncpy(channels[offset + 0].name, namePrefix, 255); strncpy(channels[offset + 0].name + prefixLen, "R", 255 - prefixLen); @@ -363,24 +369,25 @@ struct ImageSpaceGuidingBuffer{ strncpy(channels[offset + 2].name, namePrefix, 255); strncpy(channels[offset + 2].name + prefixLen, "B", 255 - prefixLen); - /* - } else if (numChannels[lay] == 4) { - strncpy(channels[offset + 0].name, namePrefix, 255); - strncpy(channels[offset + 0].name + prefixLen, "R", 255 - prefixLen); + /* + } else if (numChannels[lay] == 4) { + strncpy(channels[offset + 0].name, namePrefix, 255); + strncpy(channels[offset + 0].name + prefixLen, "R", 255 - prefixLen); - strncpy(channels[offset + 1].name, namePrefix, 255); - strncpy(channels[offset + 1].name + prefixLen, "G", 255 - prefixLen); + strncpy(channels[offset + 1].name, namePrefix, 255); + strncpy(channels[offset + 1].name + prefixLen, "G", 255 - prefixLen); - strncpy(channels[offset + 2].name, namePrefix, 255); - strncpy(channels[offset + 2].name + prefixLen, "B", 255 - prefixLen); + strncpy(channels[offset + 2].name, namePrefix, 255); + strncpy(channels[offset + 2].name + prefixLen, "B", 255 - prefixLen); - strncpy(channels[offset + 3].name, namePrefix, 255); - strncpy(channels[offset + 3].name + prefixLen, "A", 255 - prefixLen); - */ - } else { - std::cerr << "ERROR while writing " << fileName - << ": images with " << totalNumChannels << " channels are currently not supported. " - << "no file has been written." << std::endl; + strncpy(channels[offset + 3].name, namePrefix, 255); + strncpy(channels[offset + 3].name + prefixLen, "A", 255 - prefixLen); + */ + } + else + { + std::cerr << "ERROR while writing " << fileName << ": images with " << totalNumChannels << " channels are currently not supported. " << "no file has been written." + << std::endl; return; } @@ -389,33 +396,37 @@ struct ImageSpaceGuidingBuffer{ // Sort channels by the ASCII byte code of their names because thats what OpenEXR expects std::vector channelIndices; - for (int i = 0; i < totalNumChannels; ++i) channelIndices.emplace_back(i); - std::sort(channelIndices.begin(), channelIndices.end(), [&channels] (int a, int b) { + for (int i = 0; i < totalNumChannels; ++i) + channelIndices.emplace_back(i); + std::sort(channelIndices.begin(), channelIndices.end(), [&channels](int a, int b) { return strcmp(channels[a].name, channels[b].name) < 0; }); std::vector sortedChannels(totalNumChannels); - float** imagePtr = (float **) alloca(sizeof(float*) * exrImage.num_channels); - for (int i = 0; i < totalNumChannels; ++i) { + float **imagePtr = (float **)alloca(sizeof(float *) * exrImage.num_channels); + for (int i = 0; i < totalNumChannels; ++i) + { sortedChannels[i] = channels[channelIndices[i]]; imagePtr[i] = channelImages[channelIndices[i]].data(); } exrHeader.channels = sortedChannels.data(); - exrImage.images = (unsigned char**)imagePtr; + exrImage.images = (unsigned char **)imagePtr; bool writeHalf = false; // Define pixel type of the buffer and requested output pixel type in the file - exrHeader.pixel_types = (int*) alloca(sizeof(int) * exrHeader.num_channels); - exrHeader.requested_pixel_types = (int*) alloca(sizeof(int) * exrHeader.num_channels); - for (int i = 0; i < exrHeader.num_channels; i++) { + exrHeader.pixel_types = (int *)alloca(sizeof(int) * exrHeader.num_channels); + exrHeader.requested_pixel_types = (int *)alloca(sizeof(int) * exrHeader.num_channels); + for (int i = 0; i < exrHeader.num_channels; i++) + { exrHeader.pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT; exrHeader.requested_pixel_types[i] = writeHalf ? TINYEXR_PIXELTYPE_HALF : TINYEXR_PIXELTYPE_FLOAT; } - const char* errorMsg = nullptr; + const char *errorMsg = nullptr; int retCode = 0; retCode = SaveEXRImageToFile(&exrImage, &exrHeader, fileName.c_str(), &errorMsg); - if (retCode != TINYEXR_SUCCESS) { + if (retCode != TINYEXR_SUCCESS) + { std::cerr << "TinyEXR error (" << retCode << "): " << errorMsg << std::endl; FreeEXRErrorMessage(errorMsg); } @@ -423,18 +434,20 @@ struct ImageSpaceGuidingBuffer{ void update() { - if(m_useSecondMoment) + if (m_useSecondMoment) { - m_denoiser->denoise(m_contributionEstimateBuffers->contribution, m_contributionEstimateBuffers->secondMoment, m_contributionEstimateBuffers->normal, m_contributionEstimateBuffers->albedo, m_contributionEstimateBuffers->filteredContribution, m_contributionEstimateBuffers->filteredSecondMoment); + m_denoiser->denoise(m_contributionEstimateBuffers->contribution, m_contributionEstimateBuffers->secondMoment, m_contributionEstimateBuffers->normal, + m_contributionEstimateBuffers->albedo, m_contributionEstimateBuffers->filteredContribution, m_contributionEstimateBuffers->filteredSecondMoment); } else { - m_denoiser->denoise(m_contributionEstimateBuffers->contribution, m_contributionEstimateBuffers->normal, m_contributionEstimateBuffers->albedo, m_contributionEstimateBuffers->filteredContribution); + m_denoiser->denoise(m_contributionEstimateBuffers->contribution, m_contributionEstimateBuffers->normal, m_contributionEstimateBuffers->albedo, + m_contributionEstimateBuffers->filteredContribution); } m_ready = true; } - void addSample(const pgl_point2i pixel, const PGLImageSpaceSample& sample) + void addSample(const pgl_point2i pixel, const PGLImageSpaceSample &sample) { std::size_t pixelIdx = pixel.y * m_resolution.x + pixel.x; m_contributionEstimateBuffers->spp[pixelIdx] += 1; @@ -443,10 +456,12 @@ struct ImageSpaceGuidingBuffer{ m_contributionEstimateBuffers->contribution[pixelIdx] = (1.f - alpha) * m_contributionEstimateBuffers->contribution[pixelIdx] + alpha * sample.contribution; m_contributionEstimateBuffers->albedo[pixelIdx] = (1.f - alpha) * m_contributionEstimateBuffers->albedo[pixelIdx] + alpha * sample.albedo; m_contributionEstimateBuffers->normal[pixelIdx] = (1.f - alpha) * m_contributionEstimateBuffers->normal[pixelIdx] + alpha * sample.normal; - m_contributionEstimateBuffers->secondMoment[pixelIdx] = (1.f - alpha) * m_contributionEstimateBuffers->secondMoment[pixelIdx] + alpha * (sample.contribution * sample.contribution); + m_contributionEstimateBuffers->secondMoment[pixelIdx] = + (1.f - alpha) * m_contributionEstimateBuffers->secondMoment[pixelIdx] + alpha * (sample.contribution * sample.contribution); } - pgl_vec3f getContributionEstimate(const pgl_point2i pixel, const bool secondMoment = false) const{ + pgl_vec3f getContributionEstimate(const pgl_point2i pixel, const bool secondMoment = false) const + { std::size_t pixelIdx = pixel.y * m_resolution.x + pixel.x; const pgl_vec3f c = !secondMoment ? m_contributionEstimateBuffers->filteredContribution[pixelIdx] : m_contributionEstimateBuffers->filteredSecondMoment[pixelIdx]; return c; @@ -457,22 +472,22 @@ struct ImageSpaceGuidingBuffer{ return m_ready; } - void reset() + void reset() { - if(m_contributionEstimateBuffers) + if (m_contributionEstimateBuffers) { m_contributionEstimateBuffers->reset(); } m_ready = false; } - private: - bool m_ready {false}; - bool m_useSecondMoment {false}; + private: + bool m_ready{false}; + bool m_useSecondMoment{false}; pgl_point2i m_resolution; - Denoiser* m_denoiser{nullptr}; + Denoiser *m_denoiser{nullptr}; - Buffers *m_contributionEstimateBuffers {nullptr}; + Buffers *m_contributionEstimateBuffers{nullptr}; }; -} \ No newline at end of file +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/include/openpgl/common.h b/openpgl/include/openpgl/common.h index 77e5aee..a5c53a7 100644 --- a/openpgl/include/openpgl/common.h +++ b/openpgl/include/openpgl/common.h @@ -9,12 +9,12 @@ #ifdef BUILD_SHARED #ifdef _WIN32 - # ifdef openpgl_EXPORTS - # define OPENPGL_INTERFACE __declspec(dllexport) - # else - # define OPENPGL_INTERFACE __declspec(dllimport) - # endif - # define OPENPGL_DLLEXPORT __declspec(dllexport) +#ifdef openpgl_EXPORTS +#define OPENPGL_INTERFACE __declspec(dllexport) +#else +#define OPENPGL_INTERFACE __declspec(dllimport) +#endif +#define OPENPGL_DLLEXPORT __declspec(dllexport) #else #define OPENPGL_INTERFACE #define OPENPGL_DLLEXPORT __attribute__((visibility("default"))) @@ -31,174 +31,178 @@ struct pgl_vec3f { - float x, y, z; - #ifdef __cplusplus - void operator+=(const float f){ - this->x += f; - this->y += f; - this->z += f; - } - void operator-=(const float f){ - this->x -= f; - this->y -= f; - this->z -= f; - } - void operator*=(const float f){ - this->x *= f; - this->y *= f; - this->z *= f; - } - - void operator/=(const float f){ - this->x /= f; - this->y /= f; - this->z /= f; - } - #endif + float x, y, z; +#ifdef __cplusplus + void operator+=(const float f) + { + this->x += f; + this->y += f; + this->z += f; + } + void operator-=(const float f) + { + this->x -= f; + this->y -= f; + this->z -= f; + } + void operator*=(const float f) + { + this->x *= f; + this->y *= f; + this->z *= f; + } + + void operator/=(const float f) + { + this->x /= f; + this->y /= f; + this->z /= f; + } +#endif }; -inline pgl_vec3f operator+(const pgl_vec3f& v1, const pgl_vec3f& v2) +inline pgl_vec3f operator+(const pgl_vec3f &v1, const pgl_vec3f &v2) { - return {v1.x + v2.x, v1.y + v2.y, v1.z + v2.z}; + return {v1.x + v2.x, v1.y + v2.y, v1.z + v2.z}; } -inline pgl_vec3f operator+(const float f, const pgl_vec3f& v) +inline pgl_vec3f operator+(const float f, const pgl_vec3f &v) { - return {v.x + f, v.y + f, v.z + f}; + return {v.x + f, v.y + f, v.z + f}; } -inline pgl_vec3f operator+(const pgl_vec3f& v, const float f) +inline pgl_vec3f operator+(const pgl_vec3f &v, const float f) { - return {v.x + f, v.y + f, v.z + f}; + return {v.x + f, v.y + f, v.z + f}; } -inline pgl_vec3f operator-(const pgl_vec3f& v1, const pgl_vec3f& v2) +inline pgl_vec3f operator-(const pgl_vec3f &v1, const pgl_vec3f &v2) { - return {v1.x - v2.x, v1.y - v2.y, v1.z - v2.z}; + return {v1.x - v2.x, v1.y - v2.y, v1.z - v2.z}; } -inline pgl_vec3f operator-(const float f, const pgl_vec3f& v) +inline pgl_vec3f operator-(const float f, const pgl_vec3f &v) { - return {v.x - f, v.y - f, v.z - f}; + return {v.x - f, v.y - f, v.z - f}; } -inline pgl_vec3f operator-(const pgl_vec3f& v, const float f) +inline pgl_vec3f operator-(const pgl_vec3f &v, const float f) { - return {v.x - f, v.y - f, v.z - f}; + return {v.x - f, v.y - f, v.z - f}; } -inline pgl_vec3f operator*(const pgl_vec3f& v1, const pgl_vec3f& v2) +inline pgl_vec3f operator*(const pgl_vec3f &v1, const pgl_vec3f &v2) { - return {v1.x * v2.x, v1.y * v2.y, v1.z * v2.z}; + return {v1.x * v2.x, v1.y * v2.y, v1.z * v2.z}; } -inline pgl_vec3f operator*(const float f, const pgl_vec3f& v) +inline pgl_vec3f operator*(const float f, const pgl_vec3f &v) { - return {v.x * f, v.y * f, v.z * f}; + return {v.x * f, v.y * f, v.z * f}; } -inline pgl_vec3f operator*(const pgl_vec3f& v, const float f) +inline pgl_vec3f operator*(const pgl_vec3f &v, const float f) { - return {v.x * f, v.y * f, v.z * f}; + return {v.x * f, v.y * f, v.z * f}; } -inline pgl_vec3f operator/(const pgl_vec3f& v1, const pgl_vec3f& v2) +inline pgl_vec3f operator/(const pgl_vec3f &v1, const pgl_vec3f &v2) { - return {v1.x / v2.x, v1.y / v2.y, v1.z / v2.z}; + return {v1.x / v2.x, v1.y / v2.y, v1.z / v2.z}; } -inline pgl_vec3f operator/(const float f, const pgl_vec3f& v) +inline pgl_vec3f operator/(const float f, const pgl_vec3f &v) { - return {v.x / f, v.y / f, v.z / f}; + return {v.x / f, v.y / f, v.z / f}; } -inline pgl_vec3f operator/(const pgl_vec3f& v, const float f) +inline pgl_vec3f operator/(const pgl_vec3f &v, const float f) { - return {v.x / f, v.y / f, v.z / f}; + return {v.x / f, v.y / f, v.z / f}; } typedef pgl_vec3f pgl_point3f; typedef struct { - int32_t x, y, z; - #ifdef __cplusplus - #endif + int32_t x, y, z; +#ifdef __cplusplus +#endif } pgl_vec3i; typedef pgl_vec3i pgl_point3i; typedef struct { - float x, y; - #ifdef __cplusplus + float x, y; +#ifdef __cplusplus - #endif +#endif } pgl_vec2f; typedef pgl_vec2f pgl_point2f; typedef struct { - int32_t x, y; - #ifdef __cplusplus + int32_t x, y; +#ifdef __cplusplus - #endif +#endif } pgl_vec2i; typedef pgl_vec2i pgl_point2i; typedef struct { - pgl_vec3f lower, upper; + pgl_vec3f lower, upper; } pgl_box3f; inline void pglVec3f(pgl_vec3f &vec, const float x, const float y, const float z) { - vec.x = x; - vec.y = y; - vec.z = z; + vec.x = x; + vec.y = y; + vec.z = z; } inline void pglVec3fAdd(pgl_vec3f &veca, const pgl_vec3f &vecb) { - veca.x += vecb.x; - veca.y += vecb.y; - veca.z += vecb.z; + veca.x += vecb.x; + veca.y += vecb.y; + veca.z += vecb.z; } inline void pglVec2f(pgl_vec2f &vec, const float x, const float y) { - vec.x = x; - vec.y = y; + vec.x = x; + vec.y = y; } inline void pglVec2fAdd(pgl_vec2f &veca, const pgl_vec2f &vecb) { - veca.x += vecb.x; - veca.y += vecb.y; + veca.x += vecb.x; + veca.y += vecb.y; } inline void pglPoint3f(pgl_point3f &vec, const float x, const float y, const float z) { - pglVec3f(vec, x, y, z); + pglVec3f(vec, x, y, z); } inline void pglPoint2f(pgl_point2f &vec, const float x, const float y) { - pglVec2f(vec, x, y); + pglVec2f(vec, x, y); } -inline void pglBox3f(pgl_box3f& box, const float lx, const float ly, const float lz, const float ux, const float uy, const float uz) +inline void pglBox3f(pgl_box3f &box, const float lx, const float ly, const float lz, const float ux, const float uy, const float uz) { - pglVec3f(box.lower, lx, ly, lz); - pglVec3f(box.upper, ux, uy, uz); + pglVec3f(box.lower, lx, ly, lz); + pglVec3f(box.upper, ux, uy, uz); } inline pgl_vec3f normalize(pgl_vec3f n) { - const float f = 1.f / std::sqrt(n.x * n.x + n.y * n.y + n.z * n.z); - return {n.x * f, n.y * f, n.z * f}; + const float f = 1.f / std::sqrt(n.x * n.x + n.y * n.y + n.z * n.z); + return {n.x * f, n.y * f, n.z * f}; } #if defined(PGL_USE_DIRECTION_COMPRESSION) || defined(OPENPGL_DIRECTION_COMPRESSION) @@ -213,34 +217,34 @@ pgl_vec3f dequantize_direction(const uint32_t word); struct pgl_direction { - uint32_t compressed_direction; + uint32_t compressed_direction; #ifdef __cplusplus - pgl_direction() {} - pgl_direction(const float &x, const float &y, const float &z) - { - compressed_direction = quantize_direction({x, y, z}); - } - - pgl_direction(const pgl_vec3f &d) - { - compressed_direction = quantize_direction({d.x, d.y, d.z}); - } - - pgl_direction &operator=(const pgl_vec3f &direction) - { - compressed_direction = quantize_direction(direction); - return *this; - } - - bool operator!=(const pgl_direction &b) const - { - return compressed_direction != b.compressed_direction; - } - - operator pgl_vec3f() const - { - return dequantize_direction(compressed_direction); - } + pgl_direction() {} + pgl_direction(const float &x, const float &y, const float &z) + { + compressed_direction = quantize_direction({x, y, z}); + } + + pgl_direction(const pgl_vec3f &d) + { + compressed_direction = quantize_direction({d.x, d.y, d.z}); + } + + pgl_direction &operator=(const pgl_vec3f &direction) + { + compressed_direction = quantize_direction(direction); + return *this; + } + + bool operator!=(const pgl_direction &b) const + { + return compressed_direction != b.compressed_direction; + } + + operator pgl_vec3f() const + { + return dequantize_direction(compressed_direction); + } #endif }; #else @@ -260,22 +264,22 @@ pgl_vec3f rgbe2vec3f(const uint32_t rgbe); struct pgl_spectrum { - uint32_t spectrum; + uint32_t spectrum; #ifdef __cplusplus - pgl_spectrum() {} - pgl_spectrum(const pgl_vec3f rgb) - { - spectrum = vec3f2rgbe(rgb); - } - operator pgl_vec3f() const - { - return rgbe2vec3f(spectrum); - } - pgl_spectrum &operator=(const pgl_vec3f &rgb) - { - spectrum = vec3f2rgbe(rgb); - return *this; - } + pgl_spectrum() {} + pgl_spectrum(const pgl_vec3f rgb) + { + spectrum = vec3f2rgbe(rgb); + } + operator pgl_vec3f() const + { + return rgbe2vec3f(spectrum); + } + pgl_spectrum &operator=(const pgl_vec3f &rgb) + { + spectrum = vec3f2rgbe(rgb); + return *this; + } #endif }; #else diff --git a/openpgl/include/openpgl/compression.h b/openpgl/include/openpgl/compression.h index 5f3f800..c2a4d17 100644 --- a/openpgl/include/openpgl/compression.h +++ b/openpgl/include/openpgl/compression.h @@ -3,14 +3,14 @@ #pragma once -#include "common.h" -#include -#include #include +#include +#include +#include "common.h" //////////////////////////////////////////////////////////////////////// -// RGBE 32-Bit compression for radiance values (linear RGB) using +// RGBE 32-Bit compression for radiance values (linear RGB) using // shared exponent encoding as proposed by Greg Ward // (https://www.graphics.cornell.edu/~bjw/rgbe.html) //////////////////////////////////////////////////////////////////////// @@ -20,26 +20,30 @@ inline uint32_t vec3f2rgbe(const pgl_vec3f rgb) { - uint32_t rgbe; - float v; - int e; - - unsigned char* rgbe_ptr = (unsigned char*) &rgbe; - - v = rgb.x; - if (rgb.y > v) v = rgb.y; - if (rgb.z > v) v = rgb.z; - if (v < 1e-32f) { - rgbe_ptr[0] = rgbe_ptr[1] = rgbe_ptr[2] = rgbe_ptr[3] = 0; - } - else { - v = std::frexp(v,&e) * 256.0f/v; - rgbe_ptr[0] = (unsigned char) (rgb.x * v); - rgbe_ptr[1] = (unsigned char) (rgb.y * v); - rgbe_ptr[2] = (unsigned char) (rgb.z * v); - rgbe_ptr[3] = (unsigned char) (e + 128); - } - return rgbe; + uint32_t rgbe; + float v; + int e; + + unsigned char *rgbe_ptr = (unsigned char *)&rgbe; + + v = rgb.x; + if (rgb.y > v) + v = rgb.y; + if (rgb.z > v) + v = rgb.z; + if (v < 1e-32f) + { + rgbe_ptr[0] = rgbe_ptr[1] = rgbe_ptr[2] = rgbe_ptr[3] = 0; + } + else + { + v = std::frexp(v, &e) * 256.0f / v; + rgbe_ptr[0] = (unsigned char)(rgb.x * v); + rgbe_ptr[1] = (unsigned char)(rgb.y * v); + rgbe_ptr[2] = (unsigned char)(rgb.z * v); + rgbe_ptr[3] = (unsigned char)(e + 128); + } + return rgbe; } /* standard conversion from rgbe to float pixels */ @@ -48,19 +52,21 @@ inline uint32_t vec3f2rgbe(const pgl_vec3f rgb) inline pgl_vec3f rgbe2vec3f(const uint32_t rgbe) { - pgl_vec3f rgb; - const unsigned char* rgbe_ptr = (const unsigned char*) &rgbe; - - if (rgbe_ptr[3]) { //nonzero pixel - const float f = std::ldexp(1.0f,rgbe_ptr[3]-(int)(128+8)); - rgb.x = rgbe_ptr[0] * f; - rgb.y = rgbe_ptr[1] * f; - rgb.z = rgbe_ptr[2] * f; - } - else { - rgb.x = rgb.y = rgb.z = 0.f; - } - return rgb; + pgl_vec3f rgb; + const unsigned char *rgbe_ptr = (const unsigned char *)&rgbe; + + if (rgbe_ptr[3]) + { // nonzero pixel + const float f = std::ldexp(1.0f, rgbe_ptr[3] - (int)(128 + 8)); + rgb.x = rgbe_ptr[0] * f; + rgb.y = rgbe_ptr[1] * f; + rgb.z = rgbe_ptr[2] * f; + } + else + { + rgb.x = rgb.y = rgb.z = 0.f; + } + return rgb; } //////////////////////////////////////////////////////////////////////// @@ -70,43 +76,47 @@ inline pgl_vec3f rgbe2vec3f(const uint32_t rgbe) //////////////////////////////////////////////////////////////////////// // represent 0, -1 and 1 precisely by integers -inline uint32_t quantize_direction(const pgl_vec3f& n) { - const float nl1 = 1.f / (std::fabs(n.x) + std::fabs(n.y) + std::fabs(n.z)); - pgl_vec2f pn = {n.x * nl1, n.y * nl1}; - if (n.z <= 0.0f) { - pgl_vec2f signNotZero = {pn.x >= 0.0f ? 1.0f : -1.0f, pn.y >= 0.0f ? 1.0f : -1.0f}; - pgl_vec2f b = {std::abs(pn.y), std::abs(pn.x)}; - pn = {(1.f - b.x)*signNotZero.x, (1.f - b.y)*signNotZero.y}; - } - const float f = float(0x8000u); - const int32_t i = int(0x8000u); - - pn.x *= f; - pn.y *= f; - - const int32_t imin = -0x7FFF; - const int32_t imax = 0x7FFF; - const int32_t ix = std::max( imin , std::min(imax, (int32_t) pn.x)); - const int32_t iy = std::max( imin , std::min(imax, (int32_t) pn.y)); - const uint32_t ux = i + ix; - const uint32_t uy = i + iy; - return ux | (uy << 16); +inline uint32_t quantize_direction(const pgl_vec3f &n) +{ + const float nl1 = 1.f / (std::fabs(n.x) + std::fabs(n.y) + std::fabs(n.z)); + pgl_vec2f pn = {n.x * nl1, n.y * nl1}; + if (n.z <= 0.0f) + { + pgl_vec2f signNotZero = {pn.x >= 0.0f ? 1.0f : -1.0f, pn.y >= 0.0f ? 1.0f : -1.0f}; + pgl_vec2f b = {std::abs(pn.y), std::abs(pn.x)}; + pn = {(1.f - b.x) * signNotZero.x, (1.f - b.y) * signNotZero.y}; + } + const float f = float(0x8000u); + const int32_t i = int(0x8000u); + + pn.x *= f; + pn.y *= f; + + const int32_t imin = -0x7FFF; + const int32_t imax = 0x7FFF; + const int32_t ix = std::max(imin, std::min(imax, (int32_t)pn.x)); + const int32_t iy = std::max(imin, std::min(imax, (int32_t)pn.y)); + const uint32_t ux = i + ix; + const uint32_t uy = i + iy; + return ux | (uy << 16); } -inline pgl_vec3f dequantize_direction(const uint32_t word) { - int32_t ix = word & 0xFFFF; - ix -= 0x8000; - int32_t iy = word >> 16; - iy -= 0x8000; - const float f = 1.f / float(uint32_t(0x7FFF)); - pgl_vec2f n = {float(ix) * f, float(iy) * f}; - float nl1 = std::abs(n.x) + std::abs(n.y); - if (nl1 >= 1.0f) { - pgl_vec2f signNotZero = {n.x >= 0.0f ? 1.0f : -1.0f, n.y >= 0.0f ? 1.0f : -1.0f}; - pgl_vec2f b = {std::abs(n.y), std::abs(n.x)}; - n = {(1.f - b.x)*signNotZero.x, (1.f - b.y)*signNotZero.y}; - } - return normalize({n.x, n.y, 1.0f - nl1}); - -//////////////////////////////////////////////////////////////////////// +inline pgl_vec3f dequantize_direction(const uint32_t word) +{ + int32_t ix = word & 0xFFFF; + ix -= 0x8000; + int32_t iy = word >> 16; + iy -= 0x8000; + const float f = 1.f / float(uint32_t(0x7FFF)); + pgl_vec2f n = {float(ix) * f, float(iy) * f}; + float nl1 = std::abs(n.x) + std::abs(n.y); + if (nl1 >= 1.0f) + { + pgl_vec2f signNotZero = {n.x >= 0.0f ? 1.0f : -1.0f, n.y >= 0.0f ? 1.0f : -1.0f}; + pgl_vec2f b = {std::abs(n.y), std::abs(n.x)}; + n = {(1.f - b.x) * signNotZero.x, (1.f - b.y) * signNotZero.y}; + } + return normalize({n.x, n.y, 1.0f - nl1}); + + //////////////////////////////////////////////////////////////////////// } \ No newline at end of file diff --git a/openpgl/include/openpgl/config.h b/openpgl/include/openpgl/config.h index 34adade..8cf2509 100644 --- a/openpgl/include/openpgl/config.h +++ b/openpgl/include/openpgl/config.h @@ -3,7 +3,6 @@ #pragma once - #ifdef __cplusplus #include #include @@ -14,121 +13,122 @@ #include "common.h" #ifdef OPENPGL_BUILD - #ifdef OPENPGL_DEVICE_TYPE_CPU_16 - #define OPENPGL_SUPPORT_DEVICE_TYPE_CPU_16 - #endif +#ifdef OPENPGL_DEVICE_TYPE_CPU_16 +#define OPENPGL_SUPPORT_DEVICE_TYPE_CPU_16 +#endif #else - #include "defines.h" +#include "defines.h" #endif #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif #include "types.h" #define PGL_TREE_MAX_SAMPLE_PER_LEAF 32000 -enum PGL_DEVICE_TYPE -{ - PGL_DEVICE_TYPE_CPU_4, - PGL_DEVICE_TYPE_CPU_8, + enum PGL_DEVICE_TYPE + { + PGL_DEVICE_TYPE_CPU_4, + PGL_DEVICE_TYPE_CPU_8, #ifdef OPENPGL_SUPPORT_DEVICE_TYPE_CPU_16 - PGL_DEVICE_TYPE_CPU_16, + PGL_DEVICE_TYPE_CPU_16, #endif - PGL_DEVICE_TYPE_NONE, -}; + PGL_DEVICE_TYPE_NONE, + }; -struct PGLKDTreeArguments -{ - bool knnLookup {true}; - bool isKnnLookup {false}; - size_t minSamples {100}; - size_t maxSamples {PGL_TREE_MAX_SAMPLE_PER_LEAF}; - size_t maxDepth{32}; -}; - -struct PGLVMMFactoryArguments -{ - PGLVMMFactoryArguments(const size_t maxSamplesPerLeaf = PGL_TREE_MAX_SAMPLE_PER_LEAF) + struct PGLKDTreeArguments + { + bool knnLookup{true}; + bool isKnnLookup{false}; + size_t minSamples{100}; + size_t maxSamples{PGL_TREE_MAX_SAMPLE_PER_LEAF}; + size_t maxDepth{32}; + }; + + struct PGLVMMFactoryArguments { - minSamplesForSplitting = maxSamplesPerLeaf/8; - minSamplesForPartialRefitting = maxSamplesPerLeaf/8; - minSamplesForMerging = maxSamplesPerLeaf/4; - } - - // weighted EM arguments - size_t initK {PGL_VMM_MAX_COMPONENTS/2}; - float initKappa {0.5f}; + PGLVMMFactoryArguments(const size_t maxSamplesPerLeaf = PGL_TREE_MAX_SAMPLE_PER_LEAF) + { + minSamplesForSplitting = maxSamplesPerLeaf / 8; + minSamplesForPartialRefitting = maxSamplesPerLeaf / 8; + minSamplesForMerging = maxSamplesPerLeaf / 4; + } - size_t maxK {PGL_VMM_MAX_COMPONENTS}; - size_t maxEMIterrations {100}; + // weighted EM arguments + size_t initK{PGL_VMM_MAX_COMPONENTS / 2}; + float initKappa{0.5f}; - float maxKappa {PGL_VMM_MAX_KAPPA}; - //float maxMeanCosine { KappaToMeanCosine(OPENPGL_MAX_KAPPA)}; - float convergenceThreshold {0.005f}; + size_t maxK{PGL_VMM_MAX_COMPONENTS}; + size_t maxEMIterrations{100}; - // MAP prior parameters - // weight prior - float weightPrior{0.01f}; + float maxKappa{PGL_VMM_MAX_KAPPA}; + // float maxMeanCosine { KappaToMeanCosine(OPENPGL_MAX_KAPPA)}; + float convergenceThreshold{0.005f}; - // concentration/meanCosine prior - float meanCosinePriorStrength {0.2f}; - float meanCosinePrior {0.0f}; + // MAP prior parameters + // weight prior + float weightPrior{0.01f}; - // adaptive split and merge arguments - bool useSplitAndMerge {true}; + // concentration/meanCosine prior + float meanCosinePriorStrength{0.2f}; + float meanCosinePrior{0.0f}; - float splittingThreshold { 0.5f }; - float mergingThreshold { 0.025f }; + // adaptive split and merge arguments + bool useSplitAndMerge{true}; - bool partialReFit { true }; - int maxSplitItr { 1 }; + float splittingThreshold{0.5f}; + float mergingThreshold{0.025f}; - int minSamplesForSplitting { PGL_TREE_MAX_SAMPLE_PER_LEAF/8 }; - int minSamplesForPartialRefitting { PGL_TREE_MAX_SAMPLE_PER_LEAF/8 }; - int minSamplesForMerging { PGL_TREE_MAX_SAMPLE_PER_LEAF/4 }; -}; + bool partialReFit{true}; + int maxSplitItr{1}; -enum PGLDQTLeafEstimator -{ - REJECTION_SAMPLING = 0, - PER_LEAF -}; + int minSamplesForSplitting{PGL_TREE_MAX_SAMPLE_PER_LEAF / 8}; + int minSamplesForPartialRefitting{PGL_TREE_MAX_SAMPLE_PER_LEAF / 8}; + int minSamplesForMerging{PGL_TREE_MAX_SAMPLE_PER_LEAF / 4}; + }; -enum PGLDQTSplitMetric -{ - MEAN = 0, - SECOND_MOMENT -}; - -struct PGLDQTFactoryArguments -{ - PGLDQTLeafEstimator leafEstimator { PGLDQTLeafEstimator::REJECTION_SAMPLING }; - PGLDQTSplitMetric splitMetric { PGLDQTSplitMetric::MEAN }; - float splitThreshold { 0.01f }; - float footprintFactor { 1 }; - uint32_t maxLevels { 12 }; -}; - -struct PGLDebugArguments -{ - bool fitRegions {true}; -}; + enum PGLDQTLeafEstimator + { + REJECTION_SAMPLING = 0, + PER_LEAF + }; -struct PGLFieldArguments -{ - PGL_SPATIAL_STRUCTURE_TYPE spatialStructureType; - void *spatialSturctureArguments; - PGL_DIRECTIONAL_DISTRIBUTION_TYPE directionalDistributionType; - void *directionalDistributionArguments; - // for debugging - bool deterministic {false}; - PGLDebugArguments debugArguments; -}; + enum PGLDQTSplitMetric + { + MEAN = 0, + SECOND_MOMENT + }; -OPENPGL_CORE_INTERFACE void pglFieldArgumentsSetDefaults(PGLFieldArguments &fieldArguments, const PGL_SPATIAL_STRUCTURE_TYPE spatialType, const PGL_DIRECTIONAL_DISTRIBUTION_TYPE directionalType, const bool deterministic, const size_t maxSamplesPerLeaf); + struct PGLDQTFactoryArguments + { + PGLDQTLeafEstimator leafEstimator{PGLDQTLeafEstimator::REJECTION_SAMPLING}; + PGLDQTSplitMetric splitMetric{PGLDQTSplitMetric::MEAN}; + float splitThreshold{0.01f}; + float footprintFactor{1}; + uint32_t maxLevels{12}; + }; + + struct PGLDebugArguments + { + bool fitRegions{true}; + }; + struct PGLFieldArguments + { + PGL_SPATIAL_STRUCTURE_TYPE spatialStructureType; + void *spatialSturctureArguments; + PGL_DIRECTIONAL_DISTRIBUTION_TYPE directionalDistributionType; + void *directionalDistributionArguments; + // for debugging + bool deterministic{false}; + PGLDebugArguments debugArguments; + }; + + OPENPGL_CORE_INTERFACE void pglFieldArgumentsSetDefaults(PGLFieldArguments &fieldArguments, const PGL_SPATIAL_STRUCTURE_TYPE spatialType, + const PGL_DIRECTIONAL_DISTRIBUTION_TYPE directionalType, const bool deterministic, const size_t maxSamplesPerLeaf); #ifdef __cplusplus } // extern "C" diff --git a/openpgl/include/openpgl/cpp/Common.h b/openpgl/include/openpgl/cpp/Common.h index 790178d..df95c54 100644 --- a/openpgl/include/openpgl/cpp/Common.h +++ b/openpgl/include/openpgl/cpp/Common.h @@ -13,237 +13,258 @@ namespace openpgl { namespace cpp { - struct Vector3f : public pgl_vec3f{ - - Vector3f(const pgl_vec3f& v) { - this->x = v.x; - this->y = v.y; - this->z = v.z; - } - - Vector3f(float x, float y, float z) { - this->x = x; - this->y = y; - this->z = z; - } - - Vector3f(float v) { - this->x = v; - this->y = v; - this->z = v; - } - }; - - struct Vector2f : public pgl_vec2f{ - Vector2f(const pgl_vec2f& v) { - this->x = v.x; - this->y = v.y; - } - - Vector2f(float x, float y) { - this->x = x; - this->y = y; - } - - Vector2f(float v) { - this->x = v; - this->y = v; - } - }; - - struct Point3f : public pgl_point3f{ - Point3f(const pgl_point3f& p) { - this->x = p.x; - this->y = p.y; - this->z = p.z; - } - Point3f(float x, float y, float z) { - this->x = x; - this->y = y; - this->z = z; - } - - Point3f(float v) { - this->x = v; - this->y = v; - this->z = v; - } - }; - - - struct Point3i : public pgl_point3i{ - Point3i(const pgl_point3i& p) { - this->x = p.x; - this->y = p.y; - this->z = p.z; - } - Point3i(int32_t x, int32_t y, int32_t z) { - this->x = x; - this->y = y; - this->z = z; - } - - Point3i(int32_t v) { - this->x = v; - this->y = v; - this->z = v; - } - }; - - struct Point2f : public pgl_point2f{ - Point2f(const pgl_point2f& p) { - this->x = p.x; - this->y = p.y; - } - Point2f(float x, float y) { - this->x = x; - this->y = y; - } - - Point2f(float v) { - this->x = v; - this->y = v; - } - }; - - struct Point2i : public pgl_point2i{ - Point2i(const pgl_point2i& p) { - this->x = p.x; - this->y = p.y; - } - Point2i(int32_t x, int32_t y) { - this->x = x; - this->y = y; - } - - Point2i(int32_t v) { - this->x = v; - this->y = v; - } - }; - - struct Box3f : public pgl_box3f - { - Box3f(Point3f lower, Point3f upper) { - this->lower = lower; - this->upper = upper; - } - }; - - /* for a 3d vector of type pgl_vec3f. - * - * @param x - * @param y - * @param z - * @return pgl_vec3f - */ - OPENPGL_INLINE pgl_vec3f Vector3(float x, float y, float z) - { - pgl_vec3f vec3{x,y,z}; - return vec3; - } +struct Vector3f : public pgl_vec3f +{ + Vector3f(const pgl_vec3f &v) + { + this->x = v.x; + this->y = v.y; + this->z = v.z; + } + + Vector3f(float x, float y, float z) + { + this->x = x; + this->y = y; + this->z = z; + } + + Vector3f(float v) + { + this->x = v; + this->y = v; + this->z = v; + } +}; + +struct Vector2f : public pgl_vec2f +{ + Vector2f(const pgl_vec2f &v) + { + this->x = v.x; + this->y = v.y; + } + + Vector2f(float x, float y) + { + this->x = x; + this->y = y; + } + + Vector2f(float v) + { + this->x = v; + this->y = v; + } +}; + +struct Point3f : public pgl_point3f +{ + Point3f(const pgl_point3f &p) + { + this->x = p.x; + this->y = p.y; + this->z = p.z; + } + Point3f(float x, float y, float z) + { + this->x = x; + this->y = y; + this->z = z; + } + + Point3f(float v) + { + this->x = v; + this->y = v; + this->z = v; + } +}; + +struct Point3i : public pgl_point3i +{ + Point3i(const pgl_point3i &p) + { + this->x = p.x; + this->y = p.y; + this->z = p.z; + } + Point3i(int32_t x, int32_t y, int32_t z) + { + this->x = x; + this->y = y; + this->z = z; + } + + Point3i(int32_t v) + { + this->x = v; + this->y = v; + this->z = v; + } +}; + +struct Point2f : public pgl_point2f +{ + Point2f(const pgl_point2f &p) + { + this->x = p.x; + this->y = p.y; + } + Point2f(float x, float y) + { + this->x = x; + this->y = y; + } + + Point2f(float v) + { + this->x = v; + this->y = v; + } +}; + +struct Point2i : public pgl_point2i +{ + Point2i(const pgl_point2i &p) + { + this->x = p.x; + this->y = p.y; + } + Point2i(int32_t x, int32_t y) + { + this->x = x; + this->y = y; + } + + Point2i(int32_t v) + { + this->x = v; + this->y = v; + } +}; + +struct Box3f : public pgl_box3f +{ + Box3f(Point3f lower, Point3f upper) + { + this->lower = lower; + this->upper = upper; + } +}; + +/* for a 3d vector of type pgl_vec3f. + * + * @param x + * @param y + * @param z + * @return pgl_vec3f + */ +OPENPGL_INLINE pgl_vec3f Vector3(float x, float y, float z) +{ + pgl_vec3f vec3{x, y, z}; + return vec3; +} - /** - * @brief Wrapper function to simulate a C++ constructor - * for a 2d vector of type pgl_vec2f. - * - * @param x - * @param y - * @return pgl_vec2f - */ - OPENPGL_INLINE pgl_vec2f Vector2(float x, float y) - { - pgl_vec2f vec2{x,y}; - return vec2; - } +/** + * @brief Wrapper function to simulate a C++ constructor + * for a 2d vector of type pgl_vec2f. + * + * @param x + * @param y + * @return pgl_vec2f + */ +OPENPGL_INLINE pgl_vec2f Vector2(float x, float y) +{ + pgl_vec2f vec2{x, y}; + return vec2; +} - /** - * @brief Wrapper function to simulate a C++ constructor - * for a 3d position of type pgl_point3f. - * - * @param x - * @param y - * @param z - * @return pgl_point3f - */ - OPENPGL_INLINE pgl_point3f Point3(float x, float y, float z) - { - pgl_point3f point3{x,y,z}; - return point3; - } +/** + * @brief Wrapper function to simulate a C++ constructor + * for a 3d position of type pgl_point3f. + * + * @param x + * @param y + * @param z + * @return pgl_point3f + */ +OPENPGL_INLINE pgl_point3f Point3(float x, float y, float z) +{ + pgl_point3f point3{x, y, z}; + return point3; +} - /** - * @brief Wrapper function to simulate a C++ constructor - * for a 2d position of type pgl_point2f. - * - * @param x - * @param y - * @return pgl_point2f - */ - OPENPGL_INLINE pgl_vec2f Point2(float x, float y) - { - pgl_point2f point2{x,y}; - return point2; - } +/** + * @brief Wrapper function to simulate a C++ constructor + * for a 2d position of type pgl_point2f. + * + * @param x + * @param y + * @return pgl_point2f + */ +OPENPGL_INLINE pgl_vec2f Point2(float x, float y) +{ + pgl_point2f point2{x, y}; + return point2; +} - /** - * @brief Wrapper function to simulate a C++ constructor - * for a bounding box of type pgl_box3f. - * - * @param lower - * @param upper - * @return pgl_box3f - */ - OPENPGL_INLINE pgl_box3f Box3(pgl_point3f lower, pgl_point3f upper) - { - pgl_box3f box3{lower, upper}; - return box3; - } +/** + * @brief Wrapper function to simulate a C++ constructor + * for a bounding box of type pgl_box3f. + * + * @param lower + * @param upper + * @return pgl_box3f + */ +OPENPGL_INLINE pgl_box3f Box3(pgl_point3f lower, pgl_point3f upper) +{ + pgl_box3f box3{lower, upper}; + return box3; +} - /** - * @brief Wrapper function to simulate a C++ constructor - * for a bounding box of type pgl_box3f. - * - * @param lower_x - * @param lower_y - * @param lower_z - * @param upper_x - * @param upper_y - * @param upper_z - * @return pgl_box3f - */ - OPENPGL_INLINE pgl_box3f Box3(float lower_x, float lower_y, float lower_z, float upper_x, float upper_y, float upper_z) - { - pgl_box3f box3{pgl_point3f{lower_x, lower_y, lower_z}, pgl_point3f{upper_x,upper_y,upper_z}}; - return box3; - } +/** + * @brief Wrapper function to simulate a C++ constructor + * for a bounding box of type pgl_box3f. + * + * @param lower_x + * @param lower_y + * @param lower_z + * @param upper_x + * @param upper_y + * @param upper_z + * @return pgl_box3f + */ +OPENPGL_INLINE pgl_box3f Box3(float lower_x, float lower_y, float lower_z, float upper_x, float upper_y, float upper_z) +{ + pgl_box3f box3{pgl_point3f{lower_x, lower_y, lower_z}, pgl_point3f{upper_x, upper_y, upper_z}}; + return box3; +} - OPENPGL_INLINE bool IsValid(const pgl_vec3f& vec) - { - return ((vec.x > -FLT_LARGE) & (vec.x < +FLT_LARGE)) - && ((vec.y > -FLT_LARGE) & (vec.y < +FLT_LARGE)) - && ((vec.z > -FLT_LARGE) & (vec.z < +FLT_LARGE)); - } +OPENPGL_INLINE bool IsValid(const pgl_vec3f &vec) +{ + return ((vec.x > -FLT_LARGE) & (vec.x < +FLT_LARGE)) && ((vec.y > -FLT_LARGE) & (vec.y < +FLT_LARGE)) && ((vec.z > -FLT_LARGE) & (vec.z < +FLT_LARGE)); +} - OPENPGL_INLINE bool IsZero(const pgl_vec3f& vec) - { - return vec.x == 0.f && vec.y == 0.f && vec.z == 0.f; - } +OPENPGL_INLINE bool IsZero(const pgl_vec3f &vec) +{ + return vec.x == 0.f && vec.y == 0.f && vec.z == 0.f; +} - OPENPGL_INLINE float Max(const pgl_vec3f& vec) - { - return std::max(vec.x, std::max(vec.y, vec.z)); - } +OPENPGL_INLINE float Max(const pgl_vec3f &vec) +{ + return std::max(vec.x, std::max(vec.y, vec.z)); +} - OPENPGL_INLINE float Average(const pgl_vec3f& vec) - { - return (vec.x + vec.y + vec.z) / 3.f; - } +OPENPGL_INLINE float Average(const pgl_vec3f &vec) +{ + return (vec.x + vec.y + vec.z) / 3.f; +} - OPENPGL_INLINE float Average(const pgl_vec2f& vec) - { - return (vec.x + vec.y) * 0.5f; - } +OPENPGL_INLINE float Average(const pgl_vec2f &vec) +{ + return (vec.x + vec.y) * 0.5f; +} /* OPENPGL_INLINE pgl_vec3f operator+(const pgl_vec3f& v1, const pgl_vec3f& v2) { @@ -305,21 +326,25 @@ namespace cpp return {v.x / f, v.y / f, v.z / f}; } */ - OPENPGL_INLINE pgl_direction CompressDirection(const pgl_vec3f& dir) { - return dir; - } - - OPENPGL_INLINE pgl_vec3f DecompressDirection(const pgl_direction cdir) { - return cdir; - } +OPENPGL_INLINE pgl_direction CompressDirection(const pgl_vec3f &dir) +{ + return dir; +} - OPENPGL_INLINE pgl_spectrum CompressSpectrum(const pgl_vec3f& specRGB) { - return specRGB; - } +OPENPGL_INLINE pgl_vec3f DecompressDirection(const pgl_direction cdir) +{ + return cdir; +} - OPENPGL_INLINE pgl_vec3f DecompressSpectrum(const pgl_spectrum& cspecRGB) { - return cspecRGB; - } +OPENPGL_INLINE pgl_spectrum CompressSpectrum(const pgl_vec3f &specRGB) +{ + return specRGB; +} +OPENPGL_INLINE pgl_vec3f DecompressSpectrum(const pgl_spectrum &cspecRGB) +{ + return cspecRGB; } -} \ No newline at end of file + +} // namespace cpp +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/include/openpgl/cpp/Device.h b/openpgl/include/openpgl/cpp/Device.h index f8f60f1..d5dfb9d 100644 --- a/openpgl/include/openpgl/cpp/Device.h +++ b/openpgl/include/openpgl/cpp/Device.h @@ -3,13 +3,12 @@ #pragma once -#include "../openpgl.h" +#include +#include +#include "../openpgl.h" #include "Field.h" -#include -#include - namespace openpgl { namespace cpp @@ -24,22 +23,23 @@ struct Device { /** * @brief Creates a new Device object. - * + * * Creates a new Device object. The object can be optimized - * for different compute architechtures. On the CPU the device can be + * for different compute architechtures. On the CPU the device can be * optimized for different SIMD architechtures (e.g., SSE4, AVX, or AVX-512) - * + * * @param deviceType The device optimization type. */ Device(PGL_DEVICE_TYPE deviceType, size_t numThreads = 0); ~Device(); - Device(const Device&) = delete; + Device(const Device &) = delete; friend struct openpgl::cpp::Field; - private: - PGLDevice m_deviceHandle {nullptr}; + + private: + PGLDevice m_deviceHandle{nullptr}; }; //////////////////////////////////////////////////////////// @@ -58,5 +58,5 @@ OPENPGL_INLINE Device::~Device() m_deviceHandle = nullptr; } -} // cpp -} // openpgl \ No newline at end of file +} // namespace cpp +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/include/openpgl/cpp/Distribution.h b/openpgl/include/openpgl/cpp/Distribution.h index 47b0b0d..02eeb3b 100644 --- a/openpgl/include/openpgl/cpp/Distribution.h +++ b/openpgl/include/openpgl/cpp/Distribution.h @@ -12,14 +12,15 @@ namespace cpp /** * @brief The Distribution class represents the approximation of the directional guiding distribution. * E.g., this distribution can represent the incident radiance field, its product with a BSDF or phase function, - * or another target distribution. - * + * or another target distribution. + * */ struct Distribution { Distribution(PGLDistribution distributionHandle); - private: - PGLDistribution m_distributionHandle{nullptr}; + + private: + PGLDistribution m_distributionHandle{nullptr}; }; //////////////////////////////////////////////////////////// @@ -30,5 +31,5 @@ OPENPGL_INLINE Distribution::Distribution(PGLDistribution distributionHandle) { m_distributionHandle = distributionHandle; } -} -} \ No newline at end of file +} // namespace cpp +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/include/openpgl/cpp/Field.h b/openpgl/include/openpgl/cpp/Field.h index 472cb36..6b7b40a 100644 --- a/openpgl/include/openpgl/cpp/Field.h +++ b/openpgl/include/openpgl/cpp/Field.h @@ -3,15 +3,14 @@ #pragma once -#include "../openpgl.h" +#include -#include "Region.h" +#include "../openpgl.h" #include "Device.h" -#include "SampleStorage.h" #include "FieldConfig.h" #include "FieldStatistics.h" - -#include +#include "Region.h" +#include "SampleStorage.h" namespace openpgl { @@ -34,23 +33,23 @@ struct Field { /** * @brief Creates a new guiding field. - * + * * @param device The Device defining the compute architecture and optimization of the Field implementation. * @param args The configuration of the Field (e.g., spatial or directional representation). */ Field(Device *device, const FieldConfig &args); /** - * @brief Creates/Loads a guiding field from a file. - * + * @brief Creates/Loads a guiding field from a file. + * * @param device The Device defining the compute architecture and optimization of the Field implementation. * @param fieldFileName The location of the file the Field is loaded from. */ - Field(Device *device, const std::string& fieldFileName); + Field(Device *device, const std::string &fieldFileName); ~Field(); - Field(const Field&) = delete; + Field(const Field &) = delete; /** * @brief Stores Field as serialized representation to file on disk @@ -58,7 +57,7 @@ struct Field * @param fieldFileName path where to store serialized representation * @return if field could be stored to file */ - bool Store(const std::string& fieldFileName) const; + bool Store(const std::string &fieldFileName) const; /** * @brief Sets the bounding box of the scenes. @@ -70,15 +69,15 @@ struct Field * using the first sample batch. * @param bounds */ - void SetSceneBounds(const pgl_box3f& bounds); + void SetSceneBounds(const pgl_box3f &bounds); /** * @brief Get the bounding box of the scene/ - * + * * The returned bounding box merges the bounds for the surface field and * the volume field. - * - * @return pgl_box3f + * + * @return pgl_box3f */ pgl_box3f GetSceneBounds() const; @@ -87,65 +86,66 @@ struct Field * * @param sampleStorage */ - void Update(const SampleStorage& sampleStorage); + void Update(const SampleStorage &sampleStorage); /** * @brief Updates the current approximation of the surface radiance field. * * @param sampleStorage */ - void UpdateSurface(const SampleStorage& sampleStorage); + void UpdateSurface(const SampleStorage &sampleStorage); /** * @brief Updates the current approximation of the volume radiance field. * * @param sampleStorage */ - void UpdateVolume(const SampleStorage& sampleStorage); + void UpdateVolume(const SampleStorage &sampleStorage); void Reset(); /// Returns the number of performed training iterations. size_t GetIteration() const; - /// Checks if the guiding information of the Field is valid (e.g., contains no invalid directional distributions). + /// Checks if the guiding information of the Field is valid (e.g., contains no invalid directional distributions). bool Validate() const; /** * @brief Gets the statistics for the surface guiding Field. - * - * @return FieldStatistics + * + * @return FieldStatistics */ FieldStatistics GetSurfaceStatistics() const; /** * @brief Gets the statistics for the volume guiding Field. - * - * @return FieldStatistics + * + * @return FieldStatistics */ FieldStatistics GetVolumeStatistics() const; - + /// Checks if the spatial structure and directional distribution of this Field are similar to the ones stored in another Field. - bool operator==(const Field& b) const; + bool operator==(const Field &b) const; friend struct openpgl::cpp::SurfaceSamplingDistribution; friend struct openpgl::cpp::VolumeSamplingDistribution; - private: - PGLField m_fieldHandle {nullptr}; + + private: + PGLField m_fieldHandle{nullptr}; }; //////////////////////////////////////////////////////////// /// Implementation //////////////////////////////////////////////////////////// -OPENPGL_INLINE Field::Field(Device *device, const FieldConfig& cfg) +OPENPGL_INLINE Field::Field(Device *device, const FieldConfig &cfg) { OPENPGL_ASSERT(device); OPENPGL_ASSERT(device->m_deviceHandle); m_fieldHandle = pglDeviceNewField(device->m_deviceHandle, cfg.m_args); } -OPENPGL_INLINE Field::Field(Device *device, const std::string& fieldFileName) +OPENPGL_INLINE Field::Field(Device *device, const std::string &fieldFileName) { OPENPGL_ASSERT(device); OPENPGL_ASSERT(device->m_deviceHandle); @@ -161,7 +161,7 @@ OPENPGL_INLINE Field::~Field() m_fieldHandle = nullptr; } -OPENPGL_INLINE bool Field::Store(const std::string& fieldFileName) const +OPENPGL_INLINE bool Field::Store(const std::string &fieldFileName) const { OPENPGL_ASSERT(m_fieldHandle); return pglFieldStoreToFile(m_fieldHandle, fieldFileName.c_str()); @@ -173,7 +173,7 @@ OPENPGL_INLINE size_t Field::GetIteration() const return pglFieldGetIteration(m_fieldHandle); } -OPENPGL_INLINE void Field::SetSceneBounds(const pgl_box3f& bounds) +OPENPGL_INLINE void Field::SetSceneBounds(const pgl_box3f &bounds) { OPENPGL_ASSERT(m_fieldHandle); pglFieldSetSceneBounds(m_fieldHandle, bounds); @@ -185,19 +185,19 @@ OPENPGL_INLINE pgl_box3f Field::GetSceneBounds() const return pglFieldGetSceneBounds(m_fieldHandle); } -OPENPGL_INLINE void Field::Update(const SampleStorage& sampleStorage) +OPENPGL_INLINE void Field::Update(const SampleStorage &sampleStorage) { OPENPGL_ASSERT(m_fieldHandle); pglFieldUpdate(m_fieldHandle, sampleStorage.m_sampleStorageHandle); } -OPENPGL_INLINE void Field::UpdateSurface(const SampleStorage& sampleStorage) +OPENPGL_INLINE void Field::UpdateSurface(const SampleStorage &sampleStorage) { OPENPGL_ASSERT(m_fieldHandle); pglFieldUpdateSurface(m_fieldHandle, sampleStorage.m_sampleStorageHandle); } -OPENPGL_INLINE void Field::UpdateVolume(const SampleStorage& sampleStorage) +OPENPGL_INLINE void Field::UpdateVolume(const SampleStorage &sampleStorage) { OPENPGL_ASSERT(m_fieldHandle); pglFieldUpdateVolume(m_fieldHandle, sampleStorage.m_sampleStorageHandle); @@ -215,24 +215,26 @@ OPENPGL_INLINE bool Field::Validate() const return pglFieldValidate(m_fieldHandle); } -OPENPGL_INLINE bool Field::operator==(const Field& b) const +OPENPGL_INLINE bool Field::operator==(const Field &b) const { OPENPGL_ASSERT(m_fieldHandle); OPENPGL_ASSERT(b.m_fieldHandle); return pglFieldCompare(m_fieldHandle, b.m_fieldHandle); } -OPENPGL_INLINE FieldStatistics Field::GetSurfaceStatistics() const{ +OPENPGL_INLINE FieldStatistics Field::GetSurfaceStatistics() const +{ OPENPGL_ASSERT(m_fieldHandle); PGLFieldStatistics fieldStats = pglFieldGetSurfaceStatistics(m_fieldHandle); return FieldStatistics(fieldStats); } -OPENPGL_INLINE FieldStatistics Field::GetVolumeStatistics() const{ +OPENPGL_INLINE FieldStatistics Field::GetVolumeStatistics() const +{ OPENPGL_ASSERT(m_fieldHandle); PGLFieldStatistics fieldStats = pglFieldGetVolumeStatistics(m_fieldHandle); return FieldStatistics(fieldStats); } -} // cpp -} // openpgl \ No newline at end of file +} // namespace cpp +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/include/openpgl/cpp/FieldConfig.h b/openpgl/include/openpgl/cpp/FieldConfig.h index 2f8caed..88608f3 100644 --- a/openpgl/include/openpgl/cpp/FieldConfig.h +++ b/openpgl/include/openpgl/cpp/FieldConfig.h @@ -14,88 +14,95 @@ struct Field; /** * @brief The configuration for used to initialize the guiding Field. - * + * * This class contains and defines all parameters needed to initialize a guiding Field object. * These parameters contain the spatial structure or directional distribution types and the parameters - * to set up their building (i.e, sub-division behavior) and training. + * to set up their building (i.e, sub-division behavior) and training. */ struct FieldConfig { - FieldConfig() = default; ~FieldConfig() = default; - FieldConfig(const FieldConfig&) = delete; + FieldConfig(const FieldConfig &) = delete; /** * @brief Initializes the field configurations by setting all default parameters for a given combination * of spatial structure and directional distribution type and some additional parameters. - * + * * @param spatialType The spatial structure type. * @param directionalType The directional distribution type. * @param deterministic If the training/updating of the field should be deterministic (default = true). * @param maxSamplesPerLeaf The maximum number of samples per tree node (default = 32K). */ - void Init(const PGL_SPATIAL_STRUCTURE_TYPE spatialType, const PGL_DIRECTIONAL_DISTRIBUTION_TYPE directionalType, const bool deterministic = true, const size_t maxSamplesPerLeaf = 32000); + void Init(const PGL_SPATIAL_STRUCTURE_TYPE spatialType, const PGL_DIRECTIONAL_DISTRIBUTION_TYPE directionalType, const bool deterministic = true, + const size_t maxSamplesPerLeaf = 32000); /** * @brief Sets the maximum depth of the tree structure (e.g., 16). - * + * * @param maxDepth The maximum depth of the tree structure. */ void SetSpatialStructureArgMaxDepth(const size_t maxDepth); /** * @brief Enables or disables K-nearest neighbor lookup when querying a guiding cache. - * + * * @param useKnnLookup if KNN lookup should be used - */ + */ void SetUseKnnLookup(const bool useKnnLookup); /** * @brief Enables or disables if selected neighbor from the KNN-lookup is imporatnce sampled based on the distance (i.e., using a Gaussian kernel). - * + * * @param useKnnIsLookup if distance based importance sampling of the neighbors should be used - */ + */ void SetUseKnnIsLookup(const bool useKnnIsLookup); /** - * @brief For debugging and benchmarking the update of the spatial structure this function can disable + * @brief For debugging and benchmarking the update of the spatial structure this function can disable * the training of the directional distribution during the update iterations. - * + * * @param fitRegions If the directional distributions should be trained during an update iteration. */ void SetDebugArgFitRegions(const bool fitRegions); friend struct openpgl::cpp::Field; - private: - PGLFieldArguments m_args; + + private: + PGLFieldArguments m_args; }; //////////////////////////////////////////////////////////// /// Implementation //////////////////////////////////////////////////////////// -OPENPGL_INLINE void FieldConfig::Init(const PGL_SPATIAL_STRUCTURE_TYPE spatialType, const PGL_DIRECTIONAL_DISTRIBUTION_TYPE directionalType, const bool deterministic, const size_t maxSamplesPerLeaf){ +OPENPGL_INLINE void FieldConfig::Init(const PGL_SPATIAL_STRUCTURE_TYPE spatialType, const PGL_DIRECTIONAL_DISTRIBUTION_TYPE directionalType, const bool deterministic, + const size_t maxSamplesPerLeaf) +{ pglFieldArgumentsSetDefaults(m_args, spatialType, directionalType, deterministic, maxSamplesPerLeaf); } -OPENPGL_INLINE void FieldConfig::SetDebugArgFitRegions(const bool fitRegions){ +OPENPGL_INLINE void FieldConfig::SetDebugArgFitRegions(const bool fitRegions) +{ m_args.debugArguments.fitRegions = fitRegions; } -OPENPGL_INLINE void FieldConfig::SetSpatialStructureArgMaxDepth(const size_t maxDepth){ +OPENPGL_INLINE void FieldConfig::SetSpatialStructureArgMaxDepth(const size_t maxDepth) +{ reinterpret_cast(m_args.spatialSturctureArguments)->maxDepth = maxDepth; } -OPENPGL_INLINE void FieldConfig::SetUseKnnLookup(const bool useKnnLookup){ +OPENPGL_INLINE void FieldConfig::SetUseKnnLookup(const bool useKnnLookup) +{ reinterpret_cast(m_args.spatialSturctureArguments)->knnLookup = useKnnLookup; } -OPENPGL_INLINE void FieldConfig::SetUseKnnIsLookup(const bool useKnnIsLookup){ +OPENPGL_INLINE void FieldConfig::SetUseKnnIsLookup(const bool useKnnIsLookup) +{ reinterpret_cast(m_args.spatialSturctureArguments)->isKnnLookup = useKnnIsLookup; } -} // cpp -} // openpgl \ No newline at end of file +} // namespace cpp +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/include/openpgl/cpp/FieldStatistics.h b/openpgl/include/openpgl/cpp/FieldStatistics.h index 1a3414c..32283c6 100644 --- a/openpgl/include/openpgl/cpp/FieldStatistics.h +++ b/openpgl/include/openpgl/cpp/FieldStatistics.h @@ -3,18 +3,18 @@ #pragma once -#include "../openpgl.h" - #include +#include "../openpgl.h" + namespace openpgl { namespace cpp { /** - * @brief Class that stores some statistics about the spatial and directional structures of a guiding Field. - * + * @brief Class that stores some statistics about the spatial and directional structures of a guiding Field. + * * This class can be used to print information about a guiding Field. It supports printing * the information as plain string or in CSV string format. */ @@ -26,28 +26,27 @@ struct FieldStatistics /** * @brief Returns all statistics of the guiding Field as plain string. - * - * @return std::string + * + * @return std::string */ std::string ToString() const; /** * @brief Returns a CSV string containing the headers of the columns for the CSV format. - * - * @return std::string + * + * @return std::string */ std::string HeaderCSVString() const; /** * @brief Returns all statistics as one line of CSV values. - * - * @return std::string + * + * @return std::string */ std::string ToCSVString() const; - private: - PGLFieldStatistics m_fieldStatisticsHandle{nullptr}; - + private: + PGLFieldStatistics m_fieldStatisticsHandle{nullptr}; }; //////////////////////////////////////////////////////////// @@ -66,12 +65,12 @@ OPENPGL_INLINE FieldStatistics::~FieldStatistics() m_fieldStatisticsHandle = nullptr; } -OPENPGL_INLINE std::string FieldStatistics::ToString() const +OPENPGL_INLINE std::string FieldStatistics::ToString() const { OPENPGL_ASSERT(m_fieldStatisticsHandle); PGLString pglString = pglFieldStatisticsToString(m_fieldStatisticsHandle); std::string str = ""; - if(pglString.m_str) + if (pglString.m_str) str = std::string(pglString.m_str); pglReleaseString(pglString); @@ -79,12 +78,12 @@ OPENPGL_INLINE std::string FieldStatistics::ToString() const return str; } -OPENPGL_INLINE std::string FieldStatistics::HeaderCSVString() const +OPENPGL_INLINE std::string FieldStatistics::HeaderCSVString() const { OPENPGL_ASSERT(m_fieldStatisticsHandle); PGLString pglString = pglFieldStatisticsHeaderCSVString(m_fieldStatisticsHandle); std::string str = ""; - if(pglString.m_str) + if (pglString.m_str) str = std::string(pglString.m_str); pglReleaseString(pglString); @@ -92,17 +91,17 @@ OPENPGL_INLINE std::string FieldStatistics::HeaderCSVString() const return str; } -OPENPGL_INLINE std::string FieldStatistics::ToCSVString() const +OPENPGL_INLINE std::string FieldStatistics::ToCSVString() const { OPENPGL_ASSERT(m_fieldStatisticsHandle); PGLString pglString = pglFieldStatisticsToCSVString(m_fieldStatisticsHandle); std::string str = ""; - if(pglString.m_str) + if (pglString.m_str) str = std::string(pglString.m_str); pglReleaseString(pglString); return str; } -} -} +} // namespace cpp +} // namespace openpgl diff --git a/openpgl/include/openpgl/cpp/ImageSpaceGuidingBuffer.h b/openpgl/include/openpgl/cpp/ImageSpaceGuidingBuffer.h index 40ce272..d468602 100644 --- a/openpgl/include/openpgl/cpp/ImageSpaceGuidingBuffer.h +++ b/openpgl/include/openpgl/cpp/ImageSpaceGuidingBuffer.h @@ -3,11 +3,11 @@ #pragma once +#include + #include "../openpgl.h" #include "Common.h" -#include - namespace openpgl { namespace cpp @@ -17,59 +17,58 @@ namespace util /** * @brief The ImageSpaceGuidingBuffer class calculates image-space guiding information from pixel samples. - * + * * The class collects and stores the Monte-Carlo random work pixels samples generated during rendering. * The information gathered by these samples is then used, duting the @ref Update step to calculate/estimate * image-space guiding information (e.g., pixel contribtuion estimates for guided/adjoint-driven RR). - * + * */ struct ImageSpaceGuidingBuffer { typedef PGLImageSpaceSample Sample; - + /** * Creates an ImageSpaceGuidingBuffer for a given image resolution. - * + * * @param resolution The size/reslution of the image buffer */ ImageSpaceGuidingBuffer(const Point2i resolution); /** * Creates/Loads an ImageSpaceGuidingBuffer from multi-channel EXR file. - * + * * @param fileName The location of the multi-channel EXR file. */ - ImageSpaceGuidingBuffer(const std::string& fileName); + ImageSpaceGuidingBuffer(const std::string &fileName); ~ImageSpaceGuidingBuffer(); - /** * @brief Updates the image-space estimates using the previously collected/aggregated pixel samples. - * + * * Internaly this step denoises the agregated sample data and calulated all necessary image-space guiding buffer. */ void Update(); /** * @brief Adds a pixel sample to the buffer. - * + * * @param pixel The 2D pixel coordinate of the sample - * + * * @param sample The sample added to the buffer at the given pixel coordinate @ref pixel */ - void AddSample(const Point2i pixel, const Sample& sample); + void AddSample(const Point2i pixel, const Sample &sample); /** * @brief Stores the ImageSpaceGuidingBuffer into a multi-channel EXR file. - * + * * @param fileName */ - void Store(const std::string& fileName) const; + void Store(const std::string &fileName) const; /** * @brief Returns the estimate of the contirbution (i.e., expected value) of a pixel. - * + * * This quantity is usefull guided/adjoint-driven Russina roulette decisions. */ Vector3f GetPixelContributionEstimate(const Point2i pixel) const; @@ -85,8 +84,8 @@ struct ImageSpaceGuidingBuffer */ void Reset(); - private: - PGLImageSpaceGuidingBuffer m_imageSpaceGuidingBufferHandle{nullptr}; + private: + PGLImageSpaceGuidingBuffer m_imageSpaceGuidingBufferHandle{nullptr}; }; //////////////////////////////////////////////////////////// @@ -98,7 +97,7 @@ OPENPGL_INLINE ImageSpaceGuidingBuffer::ImageSpaceGuidingBuffer(const Point2i re m_imageSpaceGuidingBufferHandle = pglFieldNewImageSpaceGuidingBuffer(resolution); } -OPENPGL_INLINE ImageSpaceGuidingBuffer::ImageSpaceGuidingBuffer(const std::string& fileName) +OPENPGL_INLINE ImageSpaceGuidingBuffer::ImageSpaceGuidingBuffer(const std::string &fileName) { m_imageSpaceGuidingBufferHandle = pglFieldNewImageSpaceGuidingBufferFromFile(fileName.c_str()); } @@ -106,7 +105,7 @@ OPENPGL_INLINE ImageSpaceGuidingBuffer::ImageSpaceGuidingBuffer(const std::strin OPENPGL_INLINE ImageSpaceGuidingBuffer::~ImageSpaceGuidingBuffer() { OPENPGL_ASSERT(m_imageSpaceGuidingBufferHandle); - if(m_imageSpaceGuidingBufferHandle) + if (m_imageSpaceGuidingBufferHandle) pglReleaseImageSpaceGuidingBuffer(m_imageSpaceGuidingBufferHandle); m_imageSpaceGuidingBufferHandle = nullptr; } @@ -117,13 +116,13 @@ OPENPGL_INLINE void ImageSpaceGuidingBuffer::Update() pglImageSpaceGuidingBufferUpdate(m_imageSpaceGuidingBufferHandle); } -OPENPGL_INLINE void ImageSpaceGuidingBuffer::AddSample(const Point2i pixel, const Sample& sample) +OPENPGL_INLINE void ImageSpaceGuidingBuffer::AddSample(const Point2i pixel, const Sample &sample) { OPENPGL_ASSERT(m_imageSpaceGuidingBufferHandle); pglImageSpaceGuidingBufferAddSample(m_imageSpaceGuidingBufferHandle, pixel, sample); } -OPENPGL_INLINE void ImageSpaceGuidingBuffer::Store(const std::string& fileName) const +OPENPGL_INLINE void ImageSpaceGuidingBuffer::Store(const std::string &fileName) const { OPENPGL_ASSERT(m_imageSpaceGuidingBufferHandle); pglImageSpaceGuidingBufferStore(m_imageSpaceGuidingBufferHandle, fileName.c_str()); @@ -147,6 +146,6 @@ OPENPGL_INLINE void ImageSpaceGuidingBuffer::Reset() pglImageSpaceGuidingBufferReset(m_imageSpaceGuidingBufferHandle); } -} -} -} \ No newline at end of file +} // namespace util +} // namespace cpp +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/include/openpgl/cpp/OpenPGL.h b/openpgl/include/openpgl/cpp/OpenPGL.h index 4628a63..5eab5a3 100644 --- a/openpgl/include/openpgl/cpp/OpenPGL.h +++ b/openpgl/include/openpgl/cpp/OpenPGL.h @@ -7,13 +7,12 @@ #include #include "../openpgl.h" - #include "Common.h" #include "Distribution.h" -#include "FieldStatistics.h" -#include "FieldConfig.h" #include "Field.h" -#if defined(OPENPGL_IMAGE_SPACE_GUIDING_BUFFER) +#include "FieldConfig.h" +#include "FieldStatistics.h" +#if defined(OPENPGL_IMAGE_SPACE_GUIDING_BUFFER) #include "ImageSpaceGuidingBuffer.h" #endif #include "PathSegmentStorage.h" @@ -23,4 +22,3 @@ #include "SampleStorage.h" #include "SurfaceSamplingDistribution.h" #include "VolumeSamplingDistribution.h" - diff --git a/openpgl/include/openpgl/cpp/PathSegment.h b/openpgl/include/openpgl/cpp/PathSegment.h index c40b119..ef50308 100644 --- a/openpgl/include/openpgl/cpp/PathSegment.h +++ b/openpgl/include/openpgl/cpp/PathSegment.h @@ -12,135 +12,135 @@ namespace cpp { /** * @brief Class to store information of the current path segment. - * + * * The PathSegment class stores all required information for a path segment - * so that a list of succeeding segments (stored in a PathSegmentStorage) - * can be used to generate SampleData for training the guiding Field. - * + * so that a list of succeeding segments (stored in a PathSegmentStorage) + * can be used to generate SampleData for training the guiding Field. + * */ using PathSegment = PGLPathSegmentData; -OPENPGL_INLINE void Reset(PathSegment* pathSegment) +OPENPGL_INLINE void Reset(PathSegment *pathSegment) { OPENPGL_ASSERT(pathSegment); *pathSegment = PathSegment(); } -OPENPGL_INLINE void SetPosition(PathSegment* pathSegment, const pgl_point3f& position) +OPENPGL_INLINE void SetPosition(PathSegment *pathSegment, const pgl_point3f &position) { OPENPGL_ASSERT(pathSegment); pathSegment->position = position; } -OPENPGL_INLINE void SetNormal(PathSegment* pathSegment, const pgl_vec3f& normal) +OPENPGL_INLINE void SetNormal(PathSegment *pathSegment, const pgl_vec3f &normal) { OPENPGL_ASSERT(pathSegment); pathSegment->normal = normal; } -OPENPGL_INLINE void SetDirectionIn(PathSegment* pathSegment, const pgl_vec3f& directionIn) +OPENPGL_INLINE void SetDirectionIn(PathSegment *pathSegment, const pgl_vec3f &directionIn) { OPENPGL_ASSERT(pathSegment); pathSegment->directionIn = directionIn; } -OPENPGL_INLINE pgl_vec3f GetDirectionIn(PathSegment* pathSegment) +OPENPGL_INLINE pgl_vec3f GetDirectionIn(PathSegment *pathSegment) { OPENPGL_ASSERT(pathSegment); return pathSegment->directionIn; } -OPENPGL_INLINE void SetPDFDirectionIn(PathSegment* pathSegment, const float& pdfDirectionIn) +OPENPGL_INLINE void SetPDFDirectionIn(PathSegment *pathSegment, const float &pdfDirectionIn) { OPENPGL_ASSERT(pathSegment); pathSegment->pdfDirectionIn = pdfDirectionIn; } -OPENPGL_INLINE void SetDirectionOut(PathSegment* pathSegment, const pgl_vec3f& directionOut) +OPENPGL_INLINE void SetDirectionOut(PathSegment *pathSegment, const pgl_vec3f &directionOut) { OPENPGL_ASSERT(pathSegment); pathSegment->directionOut = directionOut; - } -OPENPGL_INLINE void SetVolumeScatter(PathSegment* pathSegment, const bool& volumeScatter) +OPENPGL_INLINE void SetVolumeScatter(PathSegment *pathSegment, const bool &volumeScatter) { OPENPGL_ASSERT(pathSegment); pathSegment->volumeScatter = volumeScatter; } -OPENPGL_INLINE void SetScatteringWeight(PathSegment* pathSegment, const pgl_vec3f& scatteringWeight){ +OPENPGL_INLINE void SetScatteringWeight(PathSegment *pathSegment, const pgl_vec3f &scatteringWeight) +{ OPENPGL_ASSERT(pathSegment); pathSegment->scatteringWeight = scatteringWeight; } -OPENPGL_INLINE void SetDirectContribution(PathSegment* pathSegment, const pgl_vec3f& directContribution) +OPENPGL_INLINE void SetDirectContribution(PathSegment *pathSegment, const pgl_vec3f &directContribution) { OPENPGL_ASSERT(pathSegment); pathSegment->directContribution = directContribution; } -OPENPGL_INLINE void AddDirectContribution(PathSegment* pathSegment, const pgl_vec3f& directContribution) +OPENPGL_INLINE void AddDirectContribution(PathSegment *pathSegment, const pgl_vec3f &directContribution) { OPENPGL_ASSERT(pathSegment); pglVec3fAdd(pathSegment->directContribution, directContribution); } -OPENPGL_INLINE void SetScatteredContribution(PathSegment* pathSegment, const pgl_vec3f& scatteredContribution) +OPENPGL_INLINE void SetScatteredContribution(PathSegment *pathSegment, const pgl_vec3f &scatteredContribution) { OPENPGL_ASSERT(pathSegment); pathSegment->scatteredContribution = scatteredContribution; } -OPENPGL_INLINE void AddScatteredContribution(PathSegment* pathSegment, const pgl_vec3f& scatteredContribution) +OPENPGL_INLINE void AddScatteredContribution(PathSegment *pathSegment, const pgl_vec3f &scatteredContribution) { OPENPGL_ASSERT(pathSegment); pglVec3fAdd(pathSegment->scatteredContribution, scatteredContribution); } -OPENPGL_INLINE void SetMiWeight(PathSegment* pathSegment, const float& miWeight) +OPENPGL_INLINE void SetMiWeight(PathSegment *pathSegment, const float &miWeight) { OPENPGL_ASSERT(pathSegment); pathSegment->miWeight = miWeight; } -OPENPGL_INLINE void SetRussianRouletteProbability(PathSegment* pathSegment, const float& russianRouletteSurvivalProbability) +OPENPGL_INLINE void SetRussianRouletteProbability(PathSegment *pathSegment, const float &russianRouletteSurvivalProbability) { OPENPGL_ASSERT(pathSegment); pathSegment->russianRouletteSurvivalProbability = russianRouletteSurvivalProbability; } -OPENPGL_INLINE void SetEta(PathSegment* pathSegment, const float& eta) +OPENPGL_INLINE void SetEta(PathSegment *pathSegment, const float &eta) { OPENPGL_ASSERT(pathSegment); pathSegment->eta = eta; } -OPENPGL_INLINE void SetIsDelta(PathSegment* pathSegment, const bool& isDelta) +OPENPGL_INLINE void SetIsDelta(PathSegment *pathSegment, const bool &isDelta) { OPENPGL_ASSERT(pathSegment); pathSegment->isDelta = isDelta; } -OPENPGL_INLINE void SetRoughness(PathSegment* pathSegment, const float& roughness) +OPENPGL_INLINE void SetRoughness(PathSegment *pathSegment, const float &roughness) { OPENPGL_ASSERT(pathSegment); pathSegment->roughness = roughness; } -OPENPGL_INLINE void SetTransmittanceWeight(PathSegment* pathSegment, const pgl_vec3f& transmittanceWeight) +OPENPGL_INLINE void SetTransmittanceWeight(PathSegment *pathSegment, const pgl_vec3f &transmittanceWeight) { OPENPGL_ASSERT(pathSegment); pathSegment->transmittanceWeight = transmittanceWeight; } // This function is deprecated -OPENPGL_INLINE void SetRegion(PathSegment* pathSegment, const Region ®ion) +OPENPGL_INLINE void SetRegion(PathSegment *pathSegment, const Region ®ion) { OPENPGL_ASSERT(pathSegment); - pathSegment->regionPtr = (void*)region.m_regionHandle; + pathSegment->regionPtr = (void *)region.m_regionHandle; } -} -} \ No newline at end of file +} // namespace cpp +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/include/openpgl/cpp/PathSegmentStorage.h b/openpgl/include/openpgl/cpp/PathSegmentStorage.h index f47da3f..2a1596a 100644 --- a/openpgl/include/openpgl/cpp/PathSegmentStorage.h +++ b/openpgl/include/openpgl/cpp/PathSegmentStorage.h @@ -13,11 +13,11 @@ namespace openpgl namespace cpp { /** - * @brief The PathSegmentStorage is a utility class to help generating SampleData during + * @brief The PathSegmentStorage is a utility class to help generating SampleData during * the path/random walk generation process. For the construction of a path/walk each new PathSegment - * is stored the PathSegmentStorage. When the walk is finished or terminated the -radiance- SampleData is - * generated using a back propagation process. The resulting samples can then be passed to the global SampleDataStorage. - * + * is stored the PathSegmentStorage. When the walk is finished or terminated the -radiance- SampleData is + * generated using a back propagation process. The resulting samples can then be passed to the global SampleDataStorage. + * */ struct PathSegmentStorage @@ -25,11 +25,11 @@ struct PathSegmentStorage PathSegmentStorage(bool trackZeroValueSamples = false); ~PathSegmentStorage(); - PathSegmentStorage(const PathSegmentStorage&) = delete; + PathSegmentStorage(const PathSegmentStorage &) = delete; /** - * @brief Reserves memory for a given number PathSegments. - * + * @brief Reserves memory for a given number PathSegments. + * * @param size The maximum number of path segments (i.e., max path length) */ void Reserve(size_t size); @@ -39,7 +39,7 @@ struct PathSegmentStorage /** * @brief Generates and internally stores -radiance- samples from the the collected path segments. - * + * * @param useNEEMiWeights If the direct illumination should be multiplied with the mis weights for NEE. * @param guideDirectLight If the gererated samples should include direct illumination. * @param rrAffectsDirectContribution If the Russian roulette probability needs to be integrated into the direct illumination. @@ -49,54 +49,54 @@ struct PathSegmentStorage /** * @brief Calculates the color estimate of the random walk/path from the path segments. - * - * This function is mainly used for debug purposes to validate if the path segments stored in the + * + * This function is mainly used for debug purposes to validate if the path segments stored in the * PathSegmentStorage cover/represent the behavior of the used renderer (e.g., path tracer). - * Ideally the output for each radom walk should match the pixel value added to the framebuffer. - * + * Ideally the output for each radom walk should match the pixel value added to the framebuffer. + * * @param rrAffectsDirectContribution If the direct contribution of a segment needs to be weighted with the RR probability. - * @return pgl_vec3f The RGB pixel value estimate for the random walk. + * @return pgl_vec3f The RGB pixel value estimate for the random walk. */ pgl_vec3f CalculatePixelEstimate(const bool rrAffectsDirectContribution) const; /** * @brief Returns a pointer to the samples generated from the path segments. - * + * * @param nSamples The size of the array of the returned pointer. * @return const SampleData* The pointer to the sample data array. */ - const SampleData* GetSamples(size_t &nSamples); + const SampleData *GetSamples(size_t &nSamples); /** * @brief Returns a pointer to the zero value samples generated from the path segments. - * + * * @param nSamples The size of the array of the returned pointer. * @return const SampleData* The pointer to the sample data array. */ - const ZeroValueSampleData* GetZeroValueSamples(size_t &nSamples); + const ZeroValueSampleData *GetZeroValueSamples(size_t &nSamples); /** - * @brief Adds a new PathSegment to the end of the path segment list and returns a pointer to it. - * - * If the number of PathSegments exceeds the number of reserved elements a nullptr is returned. - * + * @brief Adds a new PathSegment to the end of the path segment list and returns a pointer to it. + * + * If the number of PathSegments exceeds the number of reserved elements a nullptr is returned. + * * @return PathSegment* The pointer to the -currently- last segment of the storage. */ - PathSegment* NextSegment(); + PathSegment *NextSegment(); /** * @brief Adds a PathSegment at the end of the storage. - * - * If the storage has already reached its limit the segment is not added to the list. - * - * @param segment + * + * If the storage has already reached its limit the segment is not added to the list. + * + * @param segment */ - void AddSegment(const PathSegment& segment); + void AddSegment(const PathSegment &segment); /** * @brief Adds a SampleData to the sample list. - * - * @param sample + * + * @param sample */ void AddSample(SampleData sample); @@ -104,7 +104,7 @@ struct PathSegmentStorage * @brief Sets the max. distance for a generated SampleData * (i.e., the distance used when hitting an environment map). * If not set the default value is 1e6f. - * @param maxDistance + * @param maxDistance */ void SetMaxDistance(const float maxDistance); @@ -116,23 +116,23 @@ struct PathSegmentStorage /** * @brief Gets the number of stored path segments. - * + * * @return int number of stored path segments. */ int GetNumSegments() const; /** - * @brief Gets the number of samples generated from the path + * @brief Gets the number of samples generated from the path * segments and the ones added explicitly by the user. - * + * * @return int number of generated or added samples. */ int GetNumSamples() const; /** - * @brief Gets the number of zero value samples generated + * @brief Gets the number of zero value samples generated * from the path segments. - * + * * @return int number of generated or added samples. */ int GetNumZeroValueSamples() const; @@ -155,10 +155,10 @@ struct PathSegmentStorage */ bool ValidateSamples() const; - void PropagateSamples(SampleStorage* sampleStorage, const bool guideDirectLight = false, const bool useNEEMiWeights = false, const bool rrAffectsDirectContribution = true); + void PropagateSamples(SampleStorage *sampleStorage, const bool guideDirectLight = false, const bool useNEEMiWeights = false, const bool rrAffectsDirectContribution = true); - private: - PGLPathSegmentStorage m_pathSegmentStorageHandle{nullptr}; + private: + PGLPathSegmentStorage m_pathSegmentStorageHandle{nullptr}; }; //////////////////////////////////////////////////////////// @@ -166,7 +166,7 @@ struct PathSegmentStorage //////////////////////////////////////////////////////////// OPENPGL_INLINE PathSegmentStorage::PathSegmentStorage(bool trackZeroValueSamples) -{ +{ m_pathSegmentStorageHandle = pglNewPathSegmentStorage(trackZeroValueSamples); } @@ -201,26 +201,25 @@ OPENPGL_INLINE pgl_vec3f PathSegmentStorage::CalculatePixelEstimate(const bool r return pglPathSegmentStorageCalculatePixelEstimate(m_pathSegmentStorageHandle, rrAffectsDirectContribution); } -OPENPGL_INLINE const SampleData* PathSegmentStorage::GetSamples(size_t &nSamples) +OPENPGL_INLINE const SampleData *PathSegmentStorage::GetSamples(size_t &nSamples) { OPENPGL_ASSERT(m_pathSegmentStorageHandle); return pglPathSegmentStorageGetSamples(m_pathSegmentStorageHandle, nSamples); } - OPENPGL_INLINE void PathSegmentStorage::AddSample(SampleData sample) { OPENPGL_ASSERT(m_pathSegmentStorageHandle); pglPathSegmentStorageAddSample(m_pathSegmentStorageHandle, sample); } -OPENPGL_INLINE PathSegment* PathSegmentStorage::NextSegment() +OPENPGL_INLINE PathSegment *PathSegmentStorage::NextSegment() { OPENPGL_ASSERT(m_pathSegmentStorageHandle); return pglPathSegmentStorageNextSegment(m_pathSegmentStorageHandle); } -OPENPGL_INLINE void PathSegmentStorage::AddSegment(const PathSegment& segment) +OPENPGL_INLINE void PathSegmentStorage::AddSegment(const PathSegment &segment) { OPENPGL_ASSERT(m_pathSegmentStorageHandle); pglPathSegmentStorageAddSegment(m_pathSegmentStorageHandle, segment); @@ -238,7 +237,7 @@ OPENPGL_INLINE float PathSegmentStorage::GetMaxDistance() const return pglPathSegmentGetMaxDistance(m_pathSegmentStorageHandle); } -OPENPGL_INLINE int PathSegmentStorage::GetNumSegments() const +OPENPGL_INLINE int PathSegmentStorage::GetNumSegments() const { OPENPGL_ASSERT(m_pathSegmentStorageHandle); return pglPathSegmentGetNumSegments(m_pathSegmentStorageHandle); @@ -256,30 +255,31 @@ OPENPGL_INLINE int PathSegmentStorage::GetNumZeroValueSamples() const return pglPathSegmentGetNumZeroValueSamples(m_pathSegmentStorageHandle); } -OPENPGL_INLINE const ZeroValueSampleData* PathSegmentStorage::GetZeroValueSamples(size_t &nSamples) +OPENPGL_INLINE const ZeroValueSampleData *PathSegmentStorage::GetZeroValueSamples(size_t &nSamples) { OPENPGL_ASSERT(m_pathSegmentStorageHandle); return pglPathSegmentStorageGetZeroValueSamples(m_pathSegmentStorageHandle, nSamples); } OPENPGL_INLINE bool PathSegmentStorage::Validate() const -{ +{ return ValidateSegments() && ValidateSamples(); } OPENPGL_INLINE bool PathSegmentStorage::ValidateSegments() const -{ +{ OPENPGL_ASSERT(m_pathSegmentStorageHandle); return pglPathSegmentStorageValidateSegments(m_pathSegmentStorageHandle); } OPENPGL_INLINE bool PathSegmentStorage::ValidateSamples() const -{ +{ OPENPGL_ASSERT(m_pathSegmentStorageHandle); return pglPathSegmentStorageValidateSamples(m_pathSegmentStorageHandle); } -OPENPGL_INLINE void PathSegmentStorage::PropagateSamples(SampleStorage* sampleStorage, const bool guideDirectLight, const bool useNEEMiWeights, const bool rrAffectsDirectContribution) +OPENPGL_INLINE void PathSegmentStorage::PropagateSamples(SampleStorage *sampleStorage, const bool guideDirectLight, const bool useNEEMiWeights, + const bool rrAffectsDirectContribution) { OPENPGL_ASSERT(m_pathSegmentStorageHandle); OPENPGL_ASSERT(sampleStorage); @@ -287,6 +287,5 @@ OPENPGL_INLINE void PathSegmentStorage::PropagateSamples(SampleStorage* sampleSt return pglPathSegmentStoragePropagateSamples(m_pathSegmentStorageHandle, sampleStorage->m_sampleStorageHandle, guideDirectLight, useNEEMiWeights, rrAffectsDirectContribution); } - -} -} \ No newline at end of file +} // namespace cpp +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/include/openpgl/cpp/Region.h b/openpgl/include/openpgl/cpp/Region.h index 3459698..29449d6 100644 --- a/openpgl/include/openpgl/cpp/Region.h +++ b/openpgl/include/openpgl/cpp/Region.h @@ -4,7 +4,6 @@ #pragma once #include "../openpgl.h" - #include "Distribution.h" namespace openpgl @@ -13,12 +12,12 @@ namespace cpp { using PathSegment = PGLPathSegmentData; -void SetRegion(PathSegment* pathSegment, const Region ®ion); +void SetRegion(PathSegment *pathSegment, const Region ®ion); struct SurfaceSamplingDistribution; struct VolumeSamplingDistribution; /** - * @brief A Region represents a spatial region of the scene and contains the directional information (e.g., guiding distribution) for that region. - * + * @brief A Region represents a spatial region of the scene and contains the directional information (e.g., guiding distribution) for that region. + * * @deprecated Thinking about hiding the existence of the Region structure from the user */ struct Region @@ -27,31 +26,32 @@ struct Region /** * @brief Returns the internal flag if the current Region is valid or not. - * A Region is not valid if the containing appproximation of the local radiance distribution + * A Region is not valid if the containing appproximation of the local radiance distribution * is not trained yet or if a previous training pass was erroneous and resulted in an invalid - * approximation (e.g., caused by numerical problems). - * - * @return true - * @return false + * approximation (e.g., caused by numerical problems). + * + * @return true + * @return false */ - //bool GetValid() const; + // bool GetValid() const; /** * @brief Returns a copy of the approximation of the local radiance Distribution stored inside the spatial Region. * Based on the used internal representation the Distribution can be constant accross the spatial area covered by * the Region or dependent on a specific position inside the Region (e.g., parallax-aware mixtures). - * + * * @param samplePosition sampling/querying positing inside the Region * @param useParallaxComp if parallax compensation (if supported) should be used - * @return Distribution + * @return Distribution */ - //Distribution GetDistribution(pgl_point3f samplePosition, const bool &useParallaxComp) const; + // Distribution GetDistribution(pgl_point3f samplePosition, const bool &useParallaxComp) const; friend struct openpgl::cpp::SurfaceSamplingDistribution; friend struct openpgl::cpp::VolumeSamplingDistribution; - friend OPENPGL_INLINE void SetRegion(PathSegment* pathSegment, const Region ®ion); - private: - PGLRegion m_regionHandle{nullptr}; + friend OPENPGL_INLINE void SetRegion(PathSegment *pathSegment, const Region ®ion); + + private: + PGLRegion m_regionHandle{nullptr}; }; //////////////////////////////////////////////////////////// @@ -63,5 +63,5 @@ OPENPGL_INLINE Region::Region(PGLRegion regionHandle) m_regionHandle = regionHandle; } -} -} \ No newline at end of file +} // namespace cpp +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/include/openpgl/cpp/RussianRoulette.h b/openpgl/include/openpgl/cpp/RussianRoulette.h index 80ff15d..21295cd 100644 --- a/openpgl/include/openpgl/cpp/RussianRoulette.h +++ b/openpgl/include/openpgl/cpp/RussianRoulette.h @@ -12,72 +12,74 @@ namespace cpp { namespace util { - /** - * @brief Calculating the Russian Roulette survival probability using the common throughput-based RR heuristic. - * - * This function implements the throughput-based RR heuristic presented by Arvo and Kirk [AK90]. This heuristic assumes that a path will - * only have a low contribution to the final pixel estimate when it undergoes dark (i.e., low albedo) scattering events. Therefore, the survival - * probability will be low. On the other hand, if the prefix path undergoes several bright (i.e., high albedo) scattering events, it is assumed - * that the potential future contribution is also high. The @ref throughput used for RR at a given path vertex is the LTE evaluated for the prefix - * path till the given vertex times the local BSDF eval divided by the sampling PDF for the continuation direction. - * It is worth noting that if BSDF importance sampling is used, the LTE evaluation divided by the PDF becomes a low-variance - * estimator for the local directional albedo leading to a similar RR strategy as presented by Jensen [Jen01]. - * - * @param throughput The Monte-Carlo throughput weight of the prefix-path (i.e., LTE evaluation divided by PDF and previous survival probabilities). - * - * @param minSurvivalProbability The minimal returned survival probability (default = 0.0). - * - * @param maxSurvivalProbability The maximum returned survival probability (default = 1.0). - */ - OPENPGL_INLINE float StandardThroughputBasedRussianRoulette(const pgl_vec3f &throughput, const float minSurvivalProbability = 0.0f, const float maxSurvivalProbability = 1.f) - { - return std::max(minSurvivalProbability, std::min(maxSurvivalProbability, Max(throughput))); - } +/** + * @brief Calculating the Russian Roulette survival probability using the common throughput-based RR heuristic. + * + * This function implements the throughput-based RR heuristic presented by Arvo and Kirk [AK90]. This heuristic assumes that a path will + * only have a low contribution to the final pixel estimate when it undergoes dark (i.e., low albedo) scattering events. Therefore, the survival + * probability will be low. On the other hand, if the prefix path undergoes several bright (i.e., high albedo) scattering events, it is assumed + * that the potential future contribution is also high. The @ref throughput used for RR at a given path vertex is the LTE evaluated for the prefix + * path till the given vertex times the local BSDF eval divided by the sampling PDF for the continuation direction. + * It is worth noting that if BSDF importance sampling is used, the LTE evaluation divided by the PDF becomes a low-variance + * estimator for the local directional albedo leading to a similar RR strategy as presented by Jensen [Jen01]. + * + * @param throughput The Monte-Carlo throughput weight of the prefix-path (i.e., LTE evaluation divided by PDF and previous survival probabilities). + * + * @param minSurvivalProbability The minimal returned survival probability (default = 0.0). + * + * @param maxSurvivalProbability The maximum returned survival probability (default = 1.0). + */ +OPENPGL_INLINE float StandardThroughputBasedRussianRoulette(const pgl_vec3f &throughput, const float minSurvivalProbability = 0.0f, const float maxSurvivalProbability = 1.f) +{ + return std::max(minSurvivalProbability, std::min(maxSurvivalProbability, Max(throughput))); +} - /** - * @brief Calculating the Russian Roulette survival probability using the Guided/Adjoint-driven RR strategy. - * - * This function implements the Guided/Adjoint-driven RR strategy derived from the zero-variance sampling theory, - * which Vorba et al. [Vorba2016] and Herholz et al. [Vorba2019] use to guide toward the optimal RR decision for surface-based - * and volumetric light transport simulations. While the standard throughput-based RR heuristic only relies on the throughput weight of the - * prefix path to estimate the potential contribution and its importance to the estimate of the pixel value, this guided strategy also takes - * estimates of the expected pixel value ( @ref contributionEstimate ) and the expected contribution of the suffix path ( @ref adjoint ) into account. - * - * @param throughput The Monte-Carlo throughput weight of the prefix-path (i.e., LTE evaluation divided by PDF and previous survival probabilities). - * - * @param adjoint An estimate of the incoming, outgoing, or in-scattered radiance collected when continuing the suffix path. - * - * @param contributionEstimate An estimate of the final pixel value (i.e., the expected value of the random work). - * - * @param minSurvivalProbability The minimal returned survival probability (default = 0.0). - * - * @param maxSurvivalProbability The maximum returned survival probability (default = 1.0). - */ - OPENPGL_INLINE float GuidedRussianRoulette(const pgl_vec3f &throughput, const pgl_vec3f &adjoint, const pgl_vec3f &contributionEstimate, const float minSurvivalProbability = 0.0f, const float maxSurvivalProbability = 1.f) +/** + * @brief Calculating the Russian Roulette survival probability using the Guided/Adjoint-driven RR strategy. + * + * This function implements the Guided/Adjoint-driven RR strategy derived from the zero-variance sampling theory, + * which Vorba et al. [Vorba2016] and Herholz et al. [Vorba2019] use to guide toward the optimal RR decision for surface-based + * and volumetric light transport simulations. While the standard throughput-based RR heuristic only relies on the throughput weight of the + * prefix path to estimate the potential contribution and its importance to the estimate of the pixel value, this guided strategy also takes + * estimates of the expected pixel value ( @ref contributionEstimate ) and the expected contribution of the suffix path ( @ref adjoint ) into account. + * + * @param throughput The Monte-Carlo throughput weight of the prefix-path (i.e., LTE evaluation divided by PDF and previous survival probabilities). + * + * @param adjoint An estimate of the incoming, outgoing, or in-scattered radiance collected when continuing the suffix path. + * + * @param contributionEstimate An estimate of the final pixel value (i.e., the expected value of the random work). + * + * @param minSurvivalProbability The minimal returned survival probability (default = 0.0). + * + * @param maxSurvivalProbability The maximum returned survival probability (default = 1.0). + */ +OPENPGL_INLINE float GuidedRussianRoulette(const pgl_vec3f &throughput, const pgl_vec3f &adjoint, const pgl_vec3f &contributionEstimate, const float minSurvivalProbability = 0.0f, + const float maxSurvivalProbability = 1.f) +{ + float survivalProb = 1.0f; + // Guided/Adjoint-driven Russian Roulette using the weight window as described by + // Vorba and Krivanek in "Adjoint-Driven Russian Roulette and Splitting in Light Transport Simulation" + if (IsValid(adjoint) && !IsZero(adjoint)) { - float survivalProb = 1.0f; - // Guided/Adjoint-driven Russian Roulette using the weight window as described by - // Vorba and Krivanek in "Adjoint-Driven Russian Roulette and Splitting in Light Transport Simulation" - if(IsValid(adjoint) && !IsZero(adjoint)){ - const float s = 5.0f; - // weight window center - pgl_vec3f Cww = contributionEstimate / adjoint; - Cww.x = adjoint.x > 0.f ? Cww.x: 0.f; - Cww.y = adjoint.y > 0.f ? Cww.y: 0.f; - Cww.z = adjoint.z > 0.f ? Cww.z: 0.f; - OPENPGL_ASSERT(IsValid(Cww)); - // weight window lower bound - pgl_vec3f min = 2.0f * Cww / (1.0f + s); - // weight window upper bound - float fbeta = Average(throughput); - float fmin = Average(min); - fmin = fmin > 0 ? fmin : fbeta; - survivalProb = fbeta / fmin; - } - OPENPGL_ASSERT(std::isfinite(survivalProb) && !std::isnan(survivalProb)); - survivalProb = std::max(minSurvivalProbability, survivalProb); - return std::min(survivalProb, maxSurvivalProbability); + const float s = 5.0f; + // weight window center + pgl_vec3f Cww = contributionEstimate / adjoint; + Cww.x = adjoint.x > 0.f ? Cww.x : 0.f; + Cww.y = adjoint.y > 0.f ? Cww.y : 0.f; + Cww.z = adjoint.z > 0.f ? Cww.z : 0.f; + OPENPGL_ASSERT(IsValid(Cww)); + // weight window lower bound + pgl_vec3f min = 2.0f * Cww / (1.0f + s); + // weight window upper bound + float fbeta = Average(throughput); + float fmin = Average(min); + fmin = fmin > 0 ? fmin : fbeta; + survivalProb = fbeta / fmin; } + OPENPGL_ASSERT(std::isfinite(survivalProb) && !std::isnan(survivalProb)); + survivalProb = std::max(minSurvivalProbability, survivalProb); + return std::min(survivalProb, maxSurvivalProbability); } -} -} \ No newline at end of file +} // namespace util +} // namespace cpp +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/include/openpgl/cpp/SampleData.h b/openpgl/include/openpgl/cpp/SampleData.h index cb266a3..a57c478 100644 --- a/openpgl/include/openpgl/cpp/SampleData.h +++ b/openpgl/include/openpgl/cpp/SampleData.h @@ -7,14 +7,14 @@ namespace openpgl { - namespace cpp - { - /** - * @brief - * - */ - typedef PGLSampleData SampleData; +namespace cpp +{ +/** + * @brief + * + */ +typedef PGLSampleData SampleData; - typedef PGLZeroValueSampleData ZeroValueSampleData; - } -} \ No newline at end of file +typedef PGLZeroValueSampleData ZeroValueSampleData; +} // namespace cpp +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/include/openpgl/cpp/SampleStorage.h b/openpgl/include/openpgl/cpp/SampleStorage.h index be0a905..55491d5 100644 --- a/openpgl/include/openpgl/cpp/SampleStorage.h +++ b/openpgl/include/openpgl/cpp/SampleStorage.h @@ -14,75 +14,74 @@ struct PathSegmentStorage; /** * @brief The container class holding the collected sample data generated during rendering. - * + * * This container class stores the (radiance/photon) samples generated during rendering or * or at a pre-processing pass. The container is thread save and supports concurrent adding of - * samples by multiple threads. As a result only one instance of this container is needed per - * rendering. The stored samples are later used by the @ref Field class to train/learn the - * guiding field (i.e., radiance field) for a scene. + * samples by multiple threads. As a result only one instance of this container is needed per + * rendering. The stored samples are later used by the @ref Field class to train/learn the + * guiding field (i.e., radiance field) for a scene. */ struct SampleStorage { SampleStorage(); - + /** * @brief Construct a new Field object from its serialized representation * * @param fieldFileName path to serialized representation */ - SampleStorage(const std::string& sampleStorageFileName); + SampleStorage(const std::string &sampleStorageFileName); ~SampleStorage(); - SampleStorage(const SampleStorage&) = delete; + SampleStorage(const SampleStorage &) = delete; /** * @brief Stores the SampleStorage to a file. - * - * @param sampleStorageFileName + * + * @param sampleStorageFileName * @return true If saving the SampleStorage was successfull. * @return false Otherwise. */ - bool Store(const std::string& sampleStorageFileName) const; + bool Store(const std::string &sampleStorageFileName) const; /** * @brief Adds a single sample to the storage container. - * - * @param sample + * + * @param sample */ - void AddSample(const SampleData& sample); + void AddSample(const SampleData &sample); /** * @brief Adds an array of samples to the storage container. - * + * * @param samples Pointer to the beginning of the SampleData array. * @param numSamples Number of SampleData elements stored in the array. */ - void AddSamples(const SampleData* samples, size_t numSamples); + void AddSamples(const SampleData *samples, size_t numSamples); /** * @brief Add an of zero value sample the storage container. - * + * * @param samples Pointer to the beginning of the SampleData array. */ - void AddZeroValueSample(const ZeroValueSampleData& sample); + void AddZeroValueSample(const ZeroValueSampleData &sample); /** * @brief Adds an array of zero value samples to the storage container. - * + * * @param samples Pointer to the beginning of the SampleData array. * @param numSamples Number of SampleData elements stored in the array. */ - void AddZeroValueSamples(const ZeroValueSampleData* samples, size_t numSamples); + void AddZeroValueSamples(const ZeroValueSampleData *samples, size_t numSamples); /** * @brief Reserves initial space/memory for the sample storage container. - * + * * @param sizeSurface - * @param sizeVolume + * @param sizeVolume */ - void Reserve(const size_t& sizeSurface, const size_t& sizeVolume); - + void Reserve(const size_t &sizeSurface, const size_t &sizeVolume); /// Clears all internal list of surface and volume samples. void Clear(); @@ -107,30 +106,31 @@ struct SampleStorage /** * @brief Returns a volume sample from the surface sample storage. - * - * @param idx - * @return SampleData + * + * @param idx + * @return SampleData */ SampleData GetSampleSurface(const int idx) const; /** * @brief Returns a volume sample from the volume sample storage. - * - * @param idx - * @return SampleData + * + * @param idx + * @return SampleData */ SampleData GetSampleVolume(const int idx) const; - /// Checks if the samples (SampleData) stored in the SampleStorage are valid (i.e., all attributes are in valid ranges). + /// Checks if the samples (SampleData) stored in the SampleStorage are valid (i.e., all attributes are in valid ranges). bool Validate() const; /// Checks if the samples contained in another SampleStorage are the same as in the SampleStorage. - bool operator==(const SampleStorage& b) const; - + bool operator==(const SampleStorage &b) const; + friend struct Field; friend struct PathSegmentStorage; - private: - PGLSampleStorage m_sampleStorageHandle{nullptr}; + + private: + PGLSampleStorage m_sampleStorageHandle{nullptr}; }; //////////////////////////////////////////////////////////// @@ -142,7 +142,7 @@ OPENPGL_INLINE SampleStorage::SampleStorage() m_sampleStorageHandle = pglNewSampleStorage(); } -OPENPGL_INLINE SampleStorage::SampleStorage(const std::string& sampleStorageFileName) +OPENPGL_INLINE SampleStorage::SampleStorage(const std::string &sampleStorageFileName) { m_sampleStorageHandle = pglNewSampleStorageFromFile(sampleStorageFileName.c_str()); if (!m_sampleStorageHandle) @@ -156,39 +156,37 @@ OPENPGL_INLINE SampleStorage::~SampleStorage() m_sampleStorageHandle = nullptr; } -OPENPGL_INLINE bool SampleStorage::Store(const std::string& sampleStorageFileName) const +OPENPGL_INLINE bool SampleStorage::Store(const std::string &sampleStorageFileName) const { OPENPGL_ASSERT(m_sampleStorageHandle); return pglSampleStorageStoreToFile(m_sampleStorageHandle, sampleStorageFileName.c_str()); } - -OPENPGL_INLINE void SampleStorage::AddSample(const SampleData& sample) +OPENPGL_INLINE void SampleStorage::AddSample(const SampleData &sample) { OPENPGL_ASSERT(m_sampleStorageHandle); pglSampleStorageAddSample(m_sampleStorageHandle, sample); } -OPENPGL_INLINE void SampleStorage::AddSamples(const SampleData* samples, size_t numSamples) +OPENPGL_INLINE void SampleStorage::AddSamples(const SampleData *samples, size_t numSamples) { OPENPGL_ASSERT(m_sampleStorageHandle); pglSampleStorageAddSamples(m_sampleStorageHandle, samples, numSamples); } -OPENPGL_INLINE void SampleStorage::AddZeroValueSample(const ZeroValueSampleData& sample) +OPENPGL_INLINE void SampleStorage::AddZeroValueSample(const ZeroValueSampleData &sample) { OPENPGL_ASSERT(m_sampleStorageHandle); pglSampleStorageAddZeroValueSample(m_sampleStorageHandle, sample); } -OPENPGL_INLINE void SampleStorage::AddZeroValueSamples(const ZeroValueSampleData* samples, size_t numSamples) +OPENPGL_INLINE void SampleStorage::AddZeroValueSamples(const ZeroValueSampleData *samples, size_t numSamples) { OPENPGL_ASSERT(m_sampleStorageHandle); pglSampleStorageAddZeroValueSamples(m_sampleStorageHandle, samples, numSamples); } - -OPENPGL_INLINE void SampleStorage::Reserve(const size_t& sizeSurface, const size_t& sizeVolume) +OPENPGL_INLINE void SampleStorage::Reserve(const size_t &sizeSurface, const size_t &sizeVolume) { OPENPGL_ASSERT(m_sampleStorageHandle); pglSampleStorageReserve(m_sampleStorageHandle, sizeSurface, sizeVolume); @@ -254,12 +252,12 @@ OPENPGL_INLINE bool SampleStorage::Validate() const return pglSampleStorageValidate(m_sampleStorageHandle); } -OPENPGL_INLINE bool SampleStorage::operator==(const SampleStorage& b) const +OPENPGL_INLINE bool SampleStorage::operator==(const SampleStorage &b) const { OPENPGL_ASSERT(m_sampleStorageHandle); OPENPGL_ASSERT(b.m_sampleStorageHandle); return pglSampleStorageCompare(m_sampleStorageHandle, b.m_sampleStorageHandle); } -} -} \ No newline at end of file +} // namespace cpp +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/include/openpgl/cpp/SurfaceSamplingDistribution.h b/openpgl/include/openpgl/cpp/SurfaceSamplingDistribution.h index a4f2505..bafa72c 100644 --- a/openpgl/include/openpgl/cpp/SurfaceSamplingDistribution.h +++ b/openpgl/include/openpgl/cpp/SurfaceSamplingDistribution.h @@ -4,8 +4,8 @@ #pragma once #include "../openpgl.h" -#include "Region.h" #include "Field.h" +#include "Region.h" namespace openpgl { @@ -14,182 +14,179 @@ namespace cpp /** * @brief The Sampling distribution used for guidiging directional sampling decisions on surfaces. - * + * * The guided sampling distribution can be proportional to the incoming radiance or its product * with components of a BSDF model (e.g., cosine term). The class supports function for sampling and - * PDF evaluations. - * + * PDF evaluations. + * */ struct SurfaceSamplingDistribution { /** * @brief Constructs new instance of a SurfaceSamplingDistribution. - * + * * Reserves the memory need to store the guiding distribution. * Since the type/representation of distribution depends on the guiding field * a pointer to the @ref Field has to be provided. After construction * the SurfaceSamplingDistribution still need to be initialized using the @ref Init function. - * + * * @param field Pointer to the -guiding- Field. */ - SurfaceSamplingDistribution(const Field* field); + SurfaceSamplingDistribution(const Field *field); ~SurfaceSamplingDistribution(); - SurfaceSamplingDistribution(const SurfaceSamplingDistribution&) = delete; + SurfaceSamplingDistribution(const SurfaceSamplingDistribution &) = delete; /** * @brief Initializes the guiding distribution for a given position in the scene. - * + * * This function queries the guiding field for a surface guiding distribution for * given position in the scene and initializes the SurfaceSamplingDistribution * to this distribution. The resulting distribution is usually proportional to the local * incident radiance distribution at the query position. The SurfaceSamplingDistribution - * can further being improved by applying products with BSDF components (e.g., cosine). - * + * can further being improved by applying products with BSDF components (e.g., cosine). + * * @param field The guiding field of the scene. * @param pos The position the guiding distribution is queried for. * @param sample1D A random number used of a stochastic look-up is used. - * @return true - * @return false + * @return true + * @return false */ - bool Init(const Field* field, const pgl_point3f& pos, float& sample1D); + bool Init(const Field *field, const pgl_point3f &pos, float &sample1D); /** - * @brief Clears/resets the internal representation of the guiding distribution. - * + * @brief Clears/resets the internal representation of the guiding distribution. + * */ void Clear(); /** * @brief Importance samples a new direction based on the guiding distribution. - * + * * @param sample2D A 2D random variable * @return pgl_vec3f The sampled direction */ - pgl_vec3f Sample(const pgl_point2f& sample2D)const; + pgl_vec3f Sample(const pgl_point2f &sample2D) const; /** * @brief Returns the sampling PDF for a given direction when is sampled * according to the guiding distribution. - * - * @param direction + * + * @param direction * @return float The PDF for sampling @ref direction */ - float PDF(const pgl_vec3f& direction) const; - + float PDF(const pgl_vec3f &direction) const; /** * @brief Combined importance sampling and PDF calculation. * Can be more efficient to use for some distributions (e.g. DirectionQuadtree) - * + * * @param sample2D A 2D random variable * @param direction Importance sampled direction * @return float The PDF for sampling @ref direction */ - float SamplePDF(const pgl_point2f& sample2D, pgl_vec3f& direction) const; + float SamplePDF(const pgl_point2f &sample2D, pgl_vec3f &direction) const; /** * @brief Returns the PDF for the incoming radiance distibution. * This PDF does not need to relate to the sampling PDF. It is used - * to estimate the normalized incoming radiance distriubtion (e.g., for RIS). - * - * @param direction + * to estimate the normalized incoming radiance distriubtion (e.g., for RIS). + * + * @param direction * @return float The PDF for incoming radiance distribution for @ref direction */ - float IncomingRadiancePDF(const pgl_vec3f& direction) const; + float IncomingRadiancePDF(const pgl_vec3f &direction) const; /** - * @brief Returns if the used representation supports for including the cosine - * product (e.g, for diffuse surfaces) into the guiding distribution. - * - * @return true - * @return false + * @brief Returns if the used representation supports for including the cosine + * product (e.g, for diffuse surfaces) into the guiding distribution. + * + * @return true + * @return false */ bool SupportsApplyCosineProduct() const; /** * @brief Applies the product with the cosine to the guiding distribution. - * + * * @param normal The surface normal at the curren sampling position. */ - void ApplyCosineProduct(const pgl_vec3f& normal); - + void ApplyCosineProduct(const pgl_vec3f &normal); + /** * @brief Get the id of the guiding cache used to initialize the SurfaceSamplingDistribution. - * + * * @return uint32_t The id of the cache. */ uint32_t GetId() const; #ifdef OPENPGL_RADIANCE_CACHES /** * @brief Returns the incoming radiance estimates. - * - * @param direction The direction of the incoming radiance + * + * @param direction The direction of the incoming radiance * @return An estimate of the incoming direction - */ - pgl_vec3f IncomingRadiance(pgl_vec3f& direction, const bool directLightMIS) const; + */ + pgl_vec3f IncomingRadiance(pgl_vec3f &direction, const bool directLightMIS) const; /** * @brief Returns the outgoing (scattered) radiance estimates. - * - * @param direction The direction of the outgoing (scattered) radiance + * + * @param direction The direction of the outgoing (scattered) radiance * @return An estimate of the outgoing direction - */ - pgl_vec3f OutgoingRadiance(pgl_vec3f& direction) const; + */ + pgl_vec3f OutgoingRadiance(pgl_vec3f &direction) const; /** * @brief Returns the irradiance estimate for a given normal direction. * The irradiance is the integral of the product of the cosine and incident radiance. - * - * @param direction The direction of the surface normal. + * + * @param direction The direction of the surface normal. * @return An estimate of the irradiance. - */ - pgl_vec3f Irradiance(pgl_vec3f& normal, const bool directLightMIS) const; + */ + pgl_vec3f Irradiance(pgl_vec3f &normal, const bool directLightMIS) const; #endif /////////////////////////////////////// /// Future plans /////////////////////////////////////// - + /** - * @brief - * - * @param normal - * @param opaque - * @param transmission + * @brief + * + * @param normal + * @param opaque + * @param transmission */ - //void ApplyCosineProduct(const pgl_vec3f& normal, const bool opaque, const pgl_vec3f transmission); - + // void ApplyCosineProduct(const pgl_vec3f& normal, const bool opaque, const pgl_vec3f transmission); /** * @brief Validates the current guiding distribution. * The guiding distribution can be invalid if it was not * initialized before or due to (numerical) problems during the fitting process. - * + * * Note: Due to the overhead of this function, it should only be called during debugging. - * - * @return true - * @return false + * + * @return true + * @return false */ bool Validate() const; - /** * @brief @deprecated - * - * @return Region + * + * @return Region */ Region GetRegion() const; - private: - PGLSurfaceSamplingDistribution m_surfaceSamplingDistributionHandle{nullptr}; + private: + PGLSurfaceSamplingDistribution m_surfaceSamplingDistributionHandle{nullptr}; }; //////////////////////////////////////////////////////////// /// Implementation //////////////////////////////////////////////////////////// -OPENPGL_INLINE SurfaceSamplingDistribution::SurfaceSamplingDistribution(const Field* field) +OPENPGL_INLINE SurfaceSamplingDistribution::SurfaceSamplingDistribution(const Field *field) { m_surfaceSamplingDistributionHandle = pglFieldNewSurfaceSamplingDistribution(field->m_fieldHandle); } @@ -197,31 +194,30 @@ OPENPGL_INLINE SurfaceSamplingDistribution::SurfaceSamplingDistribution(const Fi OPENPGL_INLINE SurfaceSamplingDistribution::~SurfaceSamplingDistribution() { OPENPGL_ASSERT(m_surfaceSamplingDistributionHandle); - if(m_surfaceSamplingDistributionHandle) + if (m_surfaceSamplingDistributionHandle) pglReleaseSurfaceSamplingDistribution(m_surfaceSamplingDistributionHandle); m_surfaceSamplingDistributionHandle = nullptr; } - -OPENPGL_INLINE pgl_vec3f SurfaceSamplingDistribution::Sample(const pgl_point2f& sample2D)const +OPENPGL_INLINE pgl_vec3f SurfaceSamplingDistribution::Sample(const pgl_point2f &sample2D) const { OPENPGL_ASSERT(m_surfaceSamplingDistributionHandle); return pglSurfaceSamplingDistributionSample(m_surfaceSamplingDistributionHandle, sample2D); } -OPENPGL_INLINE float SurfaceSamplingDistribution::PDF(const pgl_vec3f& direction) const +OPENPGL_INLINE float SurfaceSamplingDistribution::PDF(const pgl_vec3f &direction) const { OPENPGL_ASSERT(m_surfaceSamplingDistributionHandle); return pglSurfaceSamplingDistributionPDF(m_surfaceSamplingDistributionHandle, direction); } -OPENPGL_INLINE float SurfaceSamplingDistribution::SamplePDF(const pgl_point2f& sample2D, pgl_vec3f& direction) const +OPENPGL_INLINE float SurfaceSamplingDistribution::SamplePDF(const pgl_point2f &sample2D, pgl_vec3f &direction) const { OPENPGL_ASSERT(m_surfaceSamplingDistributionHandle); - return pglSurfaceSamplingDistributionSamplePDF(m_surfaceSamplingDistributionHandle, sample2D, direction); + return pglSurfaceSamplingDistributionSamplePDF(m_surfaceSamplingDistributionHandle, sample2D, direction); } -OPENPGL_INLINE float SurfaceSamplingDistribution::IncomingRadiancePDF(const pgl_vec3f& direction) const +OPENPGL_INLINE float SurfaceSamplingDistribution::IncomingRadiancePDF(const pgl_vec3f &direction) const { OPENPGL_ASSERT(m_surfaceSamplingDistributionHandle); return pglSurfaceSamplingDistributionIncomingRadiancePDF(m_surfaceSamplingDistributionHandle, direction); @@ -239,14 +235,14 @@ OPENPGL_INLINE void SurfaceSamplingDistribution::Clear() return pglSurfaceSamplingDistributionClear(m_surfaceSamplingDistributionHandle); } -OPENPGL_INLINE bool SurfaceSamplingDistribution::Init(const Field* field, const pgl_point3f& pos, float& sample1D) +OPENPGL_INLINE bool SurfaceSamplingDistribution::Init(const Field *field, const pgl_point3f &pos, float &sample1D) { OPENPGL_ASSERT(m_surfaceSamplingDistributionHandle); OPENPGL_ASSERT(field->m_fieldHandle); return pglFieldInitSurfaceSamplingDistribution(field->m_fieldHandle, m_surfaceSamplingDistributionHandle, pos, &sample1D); } -OPENPGL_INLINE void SurfaceSamplingDistribution::ApplyCosineProduct(const pgl_vec3f& normal) +OPENPGL_INLINE void SurfaceSamplingDistribution::ApplyCosineProduct(const pgl_vec3f &normal) { OPENPGL_ASSERT(m_surfaceSamplingDistributionHandle); pglSurfaceSamplingDistributionApplyCosineProduct(m_surfaceSamplingDistributionHandle, normal); @@ -271,24 +267,24 @@ OPENPGL_INLINE uint32_t SurfaceSamplingDistribution::GetId() const return pglSurfaceSamplingDistributionGetId(m_surfaceSamplingDistributionHandle); } #ifdef OPENPGL_RADIANCE_CACHES -OPENPGL_INLINE pgl_vec3f SurfaceSamplingDistribution::IncomingRadiance(pgl_vec3f& direction, const bool directLightMIS) const +OPENPGL_INLINE pgl_vec3f SurfaceSamplingDistribution::IncomingRadiance(pgl_vec3f &direction, const bool directLightMIS) const { OPENPGL_ASSERT(m_surfaceSamplingDistributionHandle); return pglSurfaceSamplingDistributionIncomingRadiance(m_surfaceSamplingDistributionHandle, direction, directLightMIS); } -OPENPGL_INLINE pgl_vec3f SurfaceSamplingDistribution::OutgoingRadiance(pgl_vec3f& direction) const +OPENPGL_INLINE pgl_vec3f SurfaceSamplingDistribution::OutgoingRadiance(pgl_vec3f &direction) const { OPENPGL_ASSERT(m_surfaceSamplingDistributionHandle); - return pglSurfaceSamplingDistributionOutgoingRadiance(m_surfaceSamplingDistributionHandle, direction); + return pglSurfaceSamplingDistributionOutgoingRadiance(m_surfaceSamplingDistributionHandle, direction); } -OPENPGL_INLINE pgl_vec3f SurfaceSamplingDistribution::Irradiance(pgl_vec3f& normal, const bool directLightMIS) const +OPENPGL_INLINE pgl_vec3f SurfaceSamplingDistribution::Irradiance(pgl_vec3f &normal, const bool directLightMIS) const { OPENPGL_ASSERT(m_surfaceSamplingDistributionHandle); return pglSurfaceSamplingDistributionIrradiance(m_surfaceSamplingDistributionHandle, normal, directLightMIS); } #endif -} -} \ No newline at end of file +} // namespace cpp +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/include/openpgl/cpp/VolumeSamplingDistribution.h b/openpgl/include/openpgl/cpp/VolumeSamplingDistribution.h index 9fe82d4..6592cd9 100644 --- a/openpgl/include/openpgl/cpp/VolumeSamplingDistribution.h +++ b/openpgl/include/openpgl/cpp/VolumeSamplingDistribution.h @@ -4,8 +4,8 @@ #pragma once #include "../openpgl.h" -#include "Region.h" #include "Field.h" +#include "Region.h" namespace openpgl { @@ -14,153 +14,153 @@ namespace cpp /** * @brief The Sampling distribution used for guidiging directional sampling decisions inside volumes. - * + * * The guided sampling distribution can be proportional to the incoming radiance or to its product * with the phase function (e.g., single lobe HG). The class supports function for sampling and - * PDF evaluations. - * + * PDF evaluations. + * */ struct VolumeSamplingDistribution { /** * @brief Constructs new instance of a VolumeSamplingDistribution. - * + * * Reserves the memory need to store the guiding distribution. * Since the type/representation of distribution depends on the guiding field * a pointer to the @ref Field has to be provided. After construction * the VolumeSamplingDistribution still need to be initialized using the @ref Init function. - * + * * @param field Pointer to the -guiding- Field. */ - VolumeSamplingDistribution(const Field* field); - + VolumeSamplingDistribution(const Field *field); + ~VolumeSamplingDistribution(); - VolumeSamplingDistribution(const VolumeSamplingDistribution&) = delete; + VolumeSamplingDistribution(const VolumeSamplingDistribution &) = delete; /** * @brief Intitializes the guiding distibution for a given position in the scene. - * + * * This function queries the guiding field for a surface guiding distribution for * given position in the scene and initializes the VolumeSamplingDistribution * to this Distribution. The resulting distribution is usually proportional to the local * incident radiance distribution at the query position. The VolumeSamplingDistribution * can further being imporoved by applying products with phase function (e.g., single lobe HG). - * + * * Note: in anisotropic volumes it is highly recommended to add the phase function product to - * avoid variance increase due to only guiding proportional to the incident radiance distribution. - * + * avoid variance increase due to only guiding proportional to the incident radiance distribution. + * * @param field The guiding field of the scene. * @param pos The position the guiding distribution is queried for. * @param sample1D A random number used of a stoachastic look-up is used. - * @return true - * @return false + * @return true + * @return false */ - bool Init(const Field* field, const pgl_point3f& pos, float& sample1D); + bool Init(const Field *field, const pgl_point3f &pos, float &sample1D); /** - * @brief Clears/resets the internal repesentation of the guiding distribution. - * + * @brief Clears/resets the internal repesentation of the guiding distribution. + * */ void Clear(); /** * @brief Importance samples a new direction based on the guiding distribution. - * + * * @param sample2D A 2D random variable * @return pgl_vec3f The sampled direction */ - pgl_vec3f Sample(const pgl_point2f& sample2D)const; + pgl_vec3f Sample(const pgl_point2f &sample2D) const; /** * @brief Returns the sampling PDF for a given direction when is sampled * according to the guiding distribution. - * - * @param direction + * + * @param direction * @return float The PDF for sampling @ref direction */ - float PDF(const pgl_vec3f& direction) const; + float PDF(const pgl_vec3f &direction) const; /** * @brief Combined importance sampling and PDF calculation. * Can be more efficient to use for some distributions (e.g. DirectionQuadtree) - * + * * @param sample2D A 2D random variable * @param direction Importance sampled direction * @return float The PDF for sampling @ref direction */ - float SamplePDF(const pgl_point2f& sample2D, pgl_vec3f& direction) const; + float SamplePDF(const pgl_point2f &sample2D, pgl_vec3f &direction) const; /** * @brief Returns the PDF for the incoming radiance distibution. * This PDF does not need to relate to the sampling PDF. It is used - * to estimate the normalized incoming radiance distriubtion (e.g., for RIS). - * - * @param direction + * to estimate the normalized incoming radiance distriubtion (e.g., for RIS). + * + * @param direction * @return float The PDF for incoming radiance distribution for @ref direction */ - float IncomingRadiancePDF(const pgl_vec3f& direction) const; + float IncomingRadiancePDF(const pgl_vec3f &direction) const; /** - * @brief Returns if the used representation supports for including the - * product with a single lobe HenyeyGreenstein phase function into the guiding distribution. - * - * @return true - * @return false + * @brief Returns if the used representation supports for including the + * product with a single lobe HenyeyGreenstein phase function into the guiding distribution. + * + * @return true + * @return false */ bool SupportsApplySingleLobeHenyeyGreensteinProduct() const; /** * @brief Applies the product with a single lobe HenyeyGreenstein phase function * to the sampling distribution. - * + * * @param dir The direction the walk/path arrives a the sample position. * @param meanCosine The mean cosine of the HG phase function. */ - void ApplySingleLobeHenyeyGreensteinProduct(const pgl_vec3f& dir, const float meanCosine); + void ApplySingleLobeHenyeyGreensteinProduct(const pgl_vec3f &dir, const float meanCosine); /** * @brief Get the id of the guiding cache used to initialize the VolumeSamplingDistribution. - * + * * @return uint32_t The id of the cache. - */ + */ uint32_t GetId() const; #ifdef OPENPGL_RADIANCE_CACHES /** * @brief Returns the incoming radiance estimates. - * + * * @param direction The direction of the incoming radiance. * @return An estimate of the incoming direction. - */ - pgl_vec3f IncomingRadiance(pgl_vec3f& direction, const bool directLightMIS) const; + */ + pgl_vec3f IncomingRadiance(pgl_vec3f &direction, const bool directLightMIS) const; /** * @brief Returns the outgoing (scattered) radiance estimates. - * - * @param direction The direction of the outgoing (scattered) radiance. + * + * @param direction The direction of the outgoing (scattered) radiance. * @return An estimate of the outgoing direction. - */ - pgl_vec3f OutgoingRadiance(pgl_vec3f& direction) const; + */ + pgl_vec3f OutgoingRadiance(pgl_vec3f &direction) const; /** * @brief Returns the in-scattered radiance estimates. * The outgoing and in-scattered radiance estimates are estimates of the same qunatity. * Depending of the used representation (e.g., VMM, QuadTree), more precise estimates for the inscattered * might be used (e.g., VMM -> convolution of the incomming radaince). - * + * * @param direction The direction the volume radiance is scattered into. * @return An estimate of the in-scattered direction. - */ - pgl_vec3f InscatteredRadiance(pgl_vec3f& direction, const float g, const bool directLightMIS) const; + */ + pgl_vec3f InscatteredRadiance(pgl_vec3f &direction, const float g, const bool directLightMIS) const; /** * @brief Returns the estimate of the volume fluence. * The volume fluence is the radiance passing throug a point in a volume before scattering. - * + * * @return An estimate of the volume fluence direction. - */ + */ pgl_vec3f Fluence(const bool directLightMIS) const; #endif @@ -168,40 +168,40 @@ struct VolumeSamplingDistribution /// Future plans /////////////////////////////////////// -/* - void ApplyDualLobeHGProduct(const float meanCosine0, const float meanCosine1, const float mixWeight); -*/ + /* + void ApplyDualLobeHGProduct(const float meanCosine0, const float meanCosine1, const float mixWeight); + */ /** * @brief Validates the current guiding distribution. * The guiding distribution can be invalid if it was not * initialized before or due to (numerical) porblems during the fitting process. - * + * * Note: Due to the overhead of this function, it should only be called during debugging. - * - * @return true - * @return false + * + * @return true + * @return false */ bool Validate() const; - /** * @brief @deprecated - * - * @return Region + * + * @return Region */ Region GetRegion() const; friend struct openpgl::cpp::Field; - private: - PGLVolumeSamplingDistribution m_volumeSamplingDistributionHandle{nullptr}; + + private: + PGLVolumeSamplingDistribution m_volumeSamplingDistributionHandle{nullptr}; }; //////////////////////////////////////////////////////////// /// Implementation //////////////////////////////////////////////////////////// -OPENPGL_INLINE VolumeSamplingDistribution::VolumeSamplingDistribution(const Field* field) +OPENPGL_INLINE VolumeSamplingDistribution::VolumeSamplingDistribution(const Field *field) { m_volumeSamplingDistributionHandle = pglFieldNewVolumeSamplingDistribution(field->m_fieldHandle); } @@ -209,30 +209,30 @@ OPENPGL_INLINE VolumeSamplingDistribution::VolumeSamplingDistribution(const Fiel OPENPGL_INLINE VolumeSamplingDistribution::~VolumeSamplingDistribution() { OPENPGL_ASSERT(m_volumeSamplingDistributionHandle); - if(m_volumeSamplingDistributionHandle) + if (m_volumeSamplingDistributionHandle) pglReleaseVolumeSamplingDistribution(m_volumeSamplingDistributionHandle); m_volumeSamplingDistributionHandle = nullptr; } -OPENPGL_INLINE pgl_vec3f VolumeSamplingDistribution::Sample(const pgl_point2f& sample2D)const +OPENPGL_INLINE pgl_vec3f VolumeSamplingDistribution::Sample(const pgl_point2f &sample2D) const { OPENPGL_ASSERT(m_volumeSamplingDistributionHandle); return pglVolumeSamplingDistributionSample(m_volumeSamplingDistributionHandle, sample2D); } -OPENPGL_INLINE float VolumeSamplingDistribution::PDF(const pgl_vec3f& direction) const +OPENPGL_INLINE float VolumeSamplingDistribution::PDF(const pgl_vec3f &direction) const { OPENPGL_ASSERT(m_volumeSamplingDistributionHandle); return pglVolumeSamplingDistributionPDF(m_volumeSamplingDistributionHandle, direction); } -OPENPGL_INLINE float VolumeSamplingDistribution::SamplePDF(const pgl_point2f& sample2D, pgl_vec3f& direction) const +OPENPGL_INLINE float VolumeSamplingDistribution::SamplePDF(const pgl_point2f &sample2D, pgl_vec3f &direction) const { OPENPGL_ASSERT(m_volumeSamplingDistributionHandle); - return pglVolumeSamplingDistributionSamplePDF(m_volumeSamplingDistributionHandle, sample2D, direction); + return pglVolumeSamplingDistributionSamplePDF(m_volumeSamplingDistributionHandle, sample2D, direction); } -OPENPGL_INLINE float VolumeSamplingDistribution::IncomingRadiancePDF(const pgl_vec3f& direction) const +OPENPGL_INLINE float VolumeSamplingDistribution::IncomingRadiancePDF(const pgl_vec3f &direction) const { OPENPGL_ASSERT(m_volumeSamplingDistributionHandle); return pglVolumeSamplingDistributionIncomingRadiancePDF(m_volumeSamplingDistributionHandle, direction); @@ -250,7 +250,7 @@ OPENPGL_INLINE void VolumeSamplingDistribution::Clear() return pglVolumeSamplingDistributionClear(m_volumeSamplingDistributionHandle); } -OPENPGL_INLINE void VolumeSamplingDistribution::ApplySingleLobeHenyeyGreensteinProduct(const pgl_vec3f& dir, const float meanCosine) +OPENPGL_INLINE void VolumeSamplingDistribution::ApplySingleLobeHenyeyGreensteinProduct(const pgl_vec3f &dir, const float meanCosine) { OPENPGL_ASSERT(m_volumeSamplingDistributionHandle); return pglVolumeSamplingDistributionApplySingleLobeHenyeyGreensteinProduct(m_volumeSamplingDistributionHandle, dir, meanCosine); @@ -262,7 +262,7 @@ OPENPGL_INLINE bool VolumeSamplingDistribution::SupportsApplySingleLobeHenyeyGre return pglVolumeSamplingDistributionSupportsApplySingleLobeHenyeyGreensteinProduct(m_volumeSamplingDistributionHandle); } -OPENPGL_INLINE bool VolumeSamplingDistribution::Init(const Field* field, const pgl_point3f& pos, float& sample1D) +OPENPGL_INLINE bool VolumeSamplingDistribution::Init(const Field *field, const pgl_point3f &pos, float &sample1D) { OPENPGL_ASSERT(m_volumeSamplingDistributionHandle); OPENPGL_ASSERT(field->m_fieldHandle); @@ -283,22 +283,22 @@ OPENPGL_INLINE uint32_t VolumeSamplingDistribution::GetId() const } #ifdef OPENPGL_RADIANCE_CACHES -OPENPGL_INLINE pgl_vec3f VolumeSamplingDistribution::IncomingRadiance(pgl_vec3f& direction, const bool directLightMIS) const +OPENPGL_INLINE pgl_vec3f VolumeSamplingDistribution::IncomingRadiance(pgl_vec3f &direction, const bool directLightMIS) const { OPENPGL_ASSERT(m_volumeSamplingDistributionHandle); return pglVolumeSamplingDistributionIncomingRadiance(m_volumeSamplingDistributionHandle, direction, directLightMIS); } -OPENPGL_INLINE pgl_vec3f VolumeSamplingDistribution::OutgoingRadiance(pgl_vec3f& direction) const +OPENPGL_INLINE pgl_vec3f VolumeSamplingDistribution::OutgoingRadiance(pgl_vec3f &direction) const { OPENPGL_ASSERT(m_volumeSamplingDistributionHandle); - return pglVolumeSamplingDistributionOutgoingRadiance(m_volumeSamplingDistributionHandle, direction); + return pglVolumeSamplingDistributionOutgoingRadiance(m_volumeSamplingDistributionHandle, direction); } -OPENPGL_INLINE pgl_vec3f VolumeSamplingDistribution::InscatteredRadiance(pgl_vec3f& direction, const float g, const bool directLightMIS) const +OPENPGL_INLINE pgl_vec3f VolumeSamplingDistribution::InscatteredRadiance(pgl_vec3f &direction, const float g, const bool directLightMIS) const { OPENPGL_ASSERT(m_volumeSamplingDistributionHandle); - return pglVolumeSamplingDistributionInscatteredRadiance(m_volumeSamplingDistributionHandle, direction, g, directLightMIS); + return pglVolumeSamplingDistributionInscatteredRadiance(m_volumeSamplingDistributionHandle, direction, g, directLightMIS); } OPENPGL_INLINE pgl_vec3f VolumeSamplingDistribution::Fluence(const bool directLightMIS) const @@ -308,5 +308,5 @@ OPENPGL_INLINE pgl_vec3f VolumeSamplingDistribution::Fluence(const bool directLi } #endif -} -} \ No newline at end of file +} // namespace cpp +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/include/openpgl/data.h b/openpgl/include/openpgl/data.h index 49d21c1..5f55051 100644 --- a/openpgl/include/openpgl/data.h +++ b/openpgl/include/openpgl/data.h @@ -15,25 +15,25 @@ #include "common.h" /** - * @brief - * + * @brief + * */ struct PGLSampleData { enum Flags { /// point does not represent any real scene intersection point - EInsideVolume = 1<<0, + EInsideVolume = 1 << 0, /// if the samples represents direct light from a light source - EDirectLight = 1<<1 + EDirectLight = 1 << 1 }; /// the position of the sample (i.e., at which energy arrives) pgl_point3f position; /// a vector pointing into the direction the energy (e.g., radiance or importance) - /// comes from - pgl_direction direction; + /// comes from + pgl_direction direction; /// a scalar representation of the incident radiance divide by @ref pdf float weight; @@ -42,16 +42,16 @@ struct PGLSampleData /// a scalar representation of the incident radiance in RGB NOT divide by @ref pdf /// but probably weighted with @ref radianceInMISWeight if the racince comes from a /// light source. - pgl_spectrum radianceIn; + pgl_spectrum radianceIn; /// The nex float radianceInMISWeight; #endif - /// the PDF used for sampling @ref direction at @ref position + /// the PDF used for sampling @ref direction at @ref position float pdf; - /// the distance to the source of the incident radiance - float distance; + /// the distance to the source of the incident radiance + float distance; /// uint32_t flags; @@ -64,7 +64,6 @@ struct PGLSampleData #endif }; - struct PGLZeroValueSampleData { /// the position of the invalid sample @@ -80,32 +79,33 @@ struct PGLZeroValueSampleData }; /** - * @brief - * + * @brief + * */ struct PGLPathSegmentData { /// The starting position of the path segment (on a surface or inside a volume) - pgl_point3f position {0.f, 0.f, 0.f}; + pgl_point3f position{0.f, 0.f, 0.f}; /// The direction to the starting position of the next path segment - pgl_vec3f directionIn {0.f, 1.f, 0.f}; + pgl_vec3f directionIn{0.f, 1.f, 0.f}; /// The direction to the starting position of the previous path segment - pgl_vec3f directionOut {1.f, 0.f, 0.f}; + pgl_vec3f directionOut{1.f, 0.f, 0.f}; /// The surface normal at the current @ref position. Inside volumes @ref normal can be an arbritray valid direction. - pgl_vec3f normal {0.f, 0.f, 1.f}; + pgl_vec3f normal{0.f, 0.f, 1.f}; - //float distance {0.0f}; + // float distance {0.0f}; /// If the corrent segment starts inside a volume bool volumeScatter{false}; /// The PDF of sampling @ref directionIn at @ref position towards the next segment - float pdfDirectionIn {1.0f}; + float pdfDirectionIn{1.0f}; /// If the scattering interaction at @ref position was a delta Dirac (e.g., perfect mirror or glass). - bool isDelta {false}; + bool isDelta{false}; - /// The BSDF*cos or phase function evaluation at @ref position for the out-going direction @ref directionOut and the incoming direction @ref directionIn divided by the sampling PDF @ref pdfDirectionIn. + /// The BSDF*cos or phase function evaluation at @ref position for the out-going direction @ref directionOut and the incoming direction @ref directionIn divided by the sampling + /// PDF @ref pdfDirectionIn. pgl_vec3f scatteringWeight{1.0f, 1.0f, 1.0f}; /// The transmittance from the current @ref position to the @ref position of the next segment divided by the corresponding distance sampling PDF. @@ -113,11 +113,12 @@ struct PGLPathSegmentData /// the direct contribution (i.e., emission) at @ref position into @ref directionOut pgl_vec3f directContribution{0.0f, 0.0f, 0.0f}; - + /// The MIS weight which would be applied to @ref directContribution (e.g., miWeight = bsdfPDF^2/(bsdfPDF^2+neePDF^2)). - float miWeight {1.0f}; + float miWeight{1.0f}; - /// The contribution which is scattered at @ref position into @ref directionOut. There can be multiple source us such contribution (sub-surface-scattering (dipole) or scattered NEE). + /// The contribution which is scattered at @ref position into @ref directionOut. There can be multiple source us such contribution (sub-surface-scattering (dipole) or scattered + /// NEE). pgl_vec3f scatteredContribution{0.0f, 0.0f, 0.0f}; /// The probability to survive Russian roulette @@ -125,13 +126,13 @@ struct PGLPathSegmentData // BSDF information /// The refractive index (eta) of the material at @ref position. - float eta {1.0f}; + float eta{1.0f}; - /// The roughness of the material (e.g., GGX roughness on surfaces and mean cosine in volumes). - float roughness {1.0f}; + /// The roughness of the material (e.g., GGX roughness on surfaces and mean cosine in volumes). + float roughness{1.0f}; /// The pointer to the Region (DEPRECATED) - const void* regionPtr{nullptr}; + const void *regionPtr{nullptr}; }; #if defined(OPENPGL_IMAGE_SPACE_GUIDING_BUFFER) @@ -139,21 +140,22 @@ struct PGLPathSegmentData /** * @brief The class representing the contribution and some auxiliary information (e.g., albedo, normal) about the MC (random walk) sample for estimating a pixel value. */ -struct PGLImageSpaceSample{ +struct PGLImageSpaceSample +{ enum Flags { /// if the first event of the random walk is inside a volume - EVolumeEvent = 1<<0, + EVolumeEvent = 1 << 0, }; /// @brief The contribution of the MC sample. - pgl_vec3f contribution {0.f, 0.f, 0.f}; + pgl_vec3f contribution{0.f, 0.f, 0.f}; /// @brief The albedo of the surface or volume at the first hit position (on a surface or in a volume). - pgl_vec3f albedo {0.f,0.f,0.f}; + pgl_vec3f albedo{0.f, 0.f, 0.f}; /// @brief The surface normal if the first hit position is on a surface or the primary ray /// direction if the first hit is inside a volume. - pgl_vec3f normal {0.f, 0.f, -1.f}; + pgl_vec3f normal{0.f, 0.f, -1.f}; /// @brief Stores a set of binary sample attributes. - uint32_t flags {0}; + uint32_t flags{0}; #ifdef __cplusplus /// @brief Sets the bit-flag if the sample originates from a surface envent or not. @@ -176,17 +178,18 @@ struct PGLImageSpaceSample{ #endif -struct PGLString{ - char* m_str; +struct PGLString +{ + char *m_str; size_t m_size; }; #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -OPENPGL_CORE_INTERFACE void pglReleaseString(PGLString str); - + OPENPGL_CORE_INTERFACE void pglReleaseString(PGLString str); #ifdef __cplusplus } // extern "C" diff --git a/openpgl/include/openpgl/device.h b/openpgl/include/openpgl/device.h index 15a523d..06cd834 100644 --- a/openpgl/include/openpgl/device.h +++ b/openpgl/include/openpgl/device.h @@ -8,24 +8,25 @@ #include "field.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif #ifdef __cplusplus -struct Device; + struct Device; #else typedef ManagedObject Device; #endif -typedef Device *PGLDevice; + typedef Device *PGLDevice; -OPENPGL_CORE_INTERFACE PGLDevice pglNewDevice(PGL_DEVICE_TYPE deviceType, size_t numThreads); + OPENPGL_CORE_INTERFACE PGLDevice pglNewDevice(PGL_DEVICE_TYPE deviceType, size_t numThreads); -OPENPGL_CORE_INTERFACE PGLField pglDeviceNewField(PGLDevice device, PGLFieldArguments args); + OPENPGL_CORE_INTERFACE PGLField pglDeviceNewField(PGLDevice device, PGLFieldArguments args); -OPENPGL_CORE_INTERFACE PGLField pglDeviceNewFieldFromFile(PGLDevice device, const char* fieldFileName); + OPENPGL_CORE_INTERFACE PGLField pglDeviceNewFieldFromFile(PGLDevice device, const char *fieldFileName); -OPENPGL_CORE_INTERFACE void pglReleaseDevice(PGLDevice device); + OPENPGL_CORE_INTERFACE void pglReleaseDevice(PGLDevice device); #ifdef __cplusplus } // extern "C" diff --git a/openpgl/include/openpgl/distribution.h b/openpgl/include/openpgl/distribution.h index c21904f..438029e 100644 --- a/openpgl/include/openpgl/distribution.h +++ b/openpgl/include/openpgl/distribution.h @@ -3,30 +3,27 @@ #pragma once - #include "common.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif - #ifdef __cplusplus -struct Region; + struct Region; #else typedef ManagedObject Region; #endif #ifdef __cplusplus -struct Distribution; + struct Distribution; #else typedef ManagedObject Distribution; #endif - - -typedef Distribution *PGLDistribution; -typedef Region *PGLRegion; + typedef Distribution *PGLDistribution; + typedef Region *PGLRegion; #ifdef __cplusplus } // extern "C" diff --git a/openpgl/include/openpgl/field.h b/openpgl/include/openpgl/field.h index 8fff3ad..d8c4001 100644 --- a/openpgl/include/openpgl/field.h +++ b/openpgl/include/openpgl/field.h @@ -13,58 +13,60 @@ #include "common.h" #include "config.h" -#include "samplestorage.h" +#include "fieldstatistics.h" #include "region.h" +#include "samplestorage.h" #include "surfacesamplingdistribution.h" #include "volumesamplingdistribution.h" -#include "fieldstatistics.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif - #ifdef __cplusplus -struct Field; + struct Field; #else typedef ManagedObject Field; #endif -typedef Field *PGLField; + typedef Field *PGLField; -OPENPGL_CORE_INTERFACE void pglReleaseField(PGLField field); + OPENPGL_CORE_INTERFACE void pglReleaseField(PGLField field); -OPENPGL_CORE_INTERFACE bool pglFieldStoreToFile(PGLField field, const char* fieldFileName); + OPENPGL_CORE_INTERFACE bool pglFieldStoreToFile(PGLField field, const char *fieldFileName); -OPENPGL_CORE_INTERFACE size_t pglFieldGetIteration(PGLField field); + OPENPGL_CORE_INTERFACE size_t pglFieldGetIteration(PGLField field); -OPENPGL_CORE_INTERFACE void pglFieldSetSceneBounds(PGLField field, pgl_box3f bounds); + OPENPGL_CORE_INTERFACE void pglFieldSetSceneBounds(PGLField field, pgl_box3f bounds); -OPENPGL_CORE_INTERFACE pgl_box3f pglFieldGetSceneBounds(PGLField field); + OPENPGL_CORE_INTERFACE pgl_box3f pglFieldGetSceneBounds(PGLField field); -OPENPGL_CORE_INTERFACE void pglFieldUpdate(PGLField field, PGLSampleStorage sampleStorage); + OPENPGL_CORE_INTERFACE void pglFieldUpdate(PGLField field, PGLSampleStorage sampleStorage); -OPENPGL_CORE_INTERFACE void pglFieldUpdateSurface(PGLField field, PGLSampleStorage sampleStorage); + OPENPGL_CORE_INTERFACE void pglFieldUpdateSurface(PGLField field, PGLSampleStorage sampleStorage); -OPENPGL_CORE_INTERFACE void pglFieldUpdateVolume(PGLField field, PGLSampleStorage sampleStorage); + OPENPGL_CORE_INTERFACE void pglFieldUpdateVolume(PGLField field, PGLSampleStorage sampleStorage); -OPENPGL_CORE_INTERFACE void pglFieldReset(PGLField field); + OPENPGL_CORE_INTERFACE void pglFieldReset(PGLField field); -OPENPGL_CORE_INTERFACE PGLSurfaceSamplingDistribution pglFieldNewSurfaceSamplingDistribution(PGLField field); + OPENPGL_CORE_INTERFACE PGLSurfaceSamplingDistribution pglFieldNewSurfaceSamplingDistribution(PGLField field); -OPENPGL_CORE_INTERFACE bool pglFieldInitSurfaceSamplingDistribution(PGLField field, PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_point3f position, float* sample1D); + OPENPGL_CORE_INTERFACE bool pglFieldInitSurfaceSamplingDistribution(PGLField field, PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_point3f position, + float *sample1D); -OPENPGL_CORE_INTERFACE PGLVolumeSamplingDistribution pglFieldNewVolumeSamplingDistribution(PGLField field); + OPENPGL_CORE_INTERFACE PGLVolumeSamplingDistribution pglFieldNewVolumeSamplingDistribution(PGLField field); -OPENPGL_CORE_INTERFACE bool pglFieldInitVolumeSamplingDistribution(PGLField field, PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_point3f position, float* sample1D); + OPENPGL_CORE_INTERFACE bool pglFieldInitVolumeSamplingDistribution(PGLField field, PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_point3f position, + float *sample1D); -OPENPGL_CORE_INTERFACE bool pglFieldValidate(PGLField field); + OPENPGL_CORE_INTERFACE bool pglFieldValidate(PGLField field); -OPENPGL_CORE_INTERFACE bool pglFieldCompare(PGLField fieldA, PGLField fieldB); + OPENPGL_CORE_INTERFACE bool pglFieldCompare(PGLField fieldA, PGLField fieldB); -OPENPGL_CORE_INTERFACE PGLFieldStatistics pglFieldGetSurfaceStatistics(PGLField field); + OPENPGL_CORE_INTERFACE PGLFieldStatistics pglFieldGetSurfaceStatistics(PGLField field); -OPENPGL_CORE_INTERFACE PGLFieldStatistics pglFieldGetVolumeStatistics(PGLField field); + OPENPGL_CORE_INTERFACE PGLFieldStatistics pglFieldGetVolumeStatistics(PGLField field); #ifdef __cplusplus } // extern "C" diff --git a/openpgl/include/openpgl/fieldstatistics.h b/openpgl/include/openpgl/fieldstatistics.h index 98872f4..302de47 100644 --- a/openpgl/include/openpgl/fieldstatistics.h +++ b/openpgl/include/openpgl/fieldstatistics.h @@ -6,25 +6,25 @@ #include "common.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif - #ifdef __cplusplus -struct FieldStatistics; + struct FieldStatistics; #else typedef ManagedObject FieldStatistics; #endif -typedef FieldStatistics *PGLFieldStatistics; + typedef FieldStatistics *PGLFieldStatistics; -OPENPGL_CORE_INTERFACE void pglReleaseFieldStatistics(PGLFieldStatistics fieldStatistics); + OPENPGL_CORE_INTERFACE void pglReleaseFieldStatistics(PGLFieldStatistics fieldStatistics); -OPENPGL_CORE_INTERFACE PGLString pglFieldStatisticsToString(PGLFieldStatistics fieldStatistics); + OPENPGL_CORE_INTERFACE PGLString pglFieldStatisticsToString(PGLFieldStatistics fieldStatistics); -OPENPGL_CORE_INTERFACE PGLString pglFieldStatisticsHeaderCSVString(PGLFieldStatistics fieldStatistics); + OPENPGL_CORE_INTERFACE PGLString pglFieldStatisticsHeaderCSVString(PGLFieldStatistics fieldStatistics); -OPENPGL_CORE_INTERFACE PGLString pglFieldStatisticsToCSVString(PGLFieldStatistics fieldStatistics); + OPENPGL_CORE_INTERFACE PGLString pglFieldStatisticsToCSVString(PGLFieldStatistics fieldStatistics); #ifdef __cplusplus } // extern "C" diff --git a/openpgl/include/openpgl/imagespaceguidingbuffer.h b/openpgl/include/openpgl/imagespaceguidingbuffer.h index 7273092..0316618 100644 --- a/openpgl/include/openpgl/imagespaceguidingbuffer.h +++ b/openpgl/include/openpgl/imagespaceguidingbuffer.h @@ -3,40 +3,39 @@ #pragma once - #include "common.h" #include "region.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif #ifdef __cplusplus -struct ImageSpaceGuidingBuffer; + struct ImageSpaceGuidingBuffer; #else typedef ManagedObject ImageSpaceGuidingBuffer; #endif -typedef ImageSpaceGuidingBuffer *PGLImageSpaceGuidingBuffer; - -OPENPGL_CORE_INTERFACE PGLImageSpaceGuidingBuffer pglFieldNewImageSpaceGuidingBuffer(const pgl_point2i resolution); + typedef ImageSpaceGuidingBuffer *PGLImageSpaceGuidingBuffer; -OPENPGL_CORE_INTERFACE PGLImageSpaceGuidingBuffer pglFieldNewImageSpaceGuidingBufferFromFile(const char* fileName); + OPENPGL_CORE_INTERFACE PGLImageSpaceGuidingBuffer pglFieldNewImageSpaceGuidingBuffer(const pgl_point2i resolution); -OPENPGL_CORE_INTERFACE void pglReleaseImageSpaceGuidingBuffer(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer); + OPENPGL_CORE_INTERFACE PGLImageSpaceGuidingBuffer pglFieldNewImageSpaceGuidingBufferFromFile(const char *fileName); -OPENPGL_CORE_INTERFACE void pglImageSpaceGuidingBufferUpdate(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer); + OPENPGL_CORE_INTERFACE void pglReleaseImageSpaceGuidingBuffer(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer); -OPENPGL_CORE_INTERFACE void pglImageSpaceGuidingBufferAddSample(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer, const pgl_point2i pixel, const PGLImageSpaceSample sample); + OPENPGL_CORE_INTERFACE void pglImageSpaceGuidingBufferUpdate(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer); -OPENPGL_CORE_INTERFACE void pglImageSpaceGuidingBufferStore(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer, const char* fileName); + OPENPGL_CORE_INTERFACE void pglImageSpaceGuidingBufferAddSample(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer, const pgl_point2i pixel, const PGLImageSpaceSample sample); -OPENPGL_CORE_INTERFACE pgl_vec3f pglImageSpaceGuidingBufferGetPixelContributionEstimate(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer, const pgl_point2i pixel); + OPENPGL_CORE_INTERFACE void pglImageSpaceGuidingBufferStore(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer, const char *fileName); -OPENPGL_CORE_INTERFACE bool pglImageSpaceGuidingBufferIsReady(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer); + OPENPGL_CORE_INTERFACE pgl_vec3f pglImageSpaceGuidingBufferGetPixelContributionEstimate(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer, const pgl_point2i pixel); -OPENPGL_CORE_INTERFACE void pglImageSpaceGuidingBufferReset(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer); + OPENPGL_CORE_INTERFACE bool pglImageSpaceGuidingBufferIsReady(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer); + OPENPGL_CORE_INTERFACE void pglImageSpaceGuidingBufferReset(PGLImageSpaceGuidingBuffer imageSpaceGuidingBuffer); #ifdef __cplusplus } // extern "C" diff --git a/openpgl/include/openpgl/openpgl.h b/openpgl/include/openpgl/openpgl.h index 5906d55..11ce5ab 100644 --- a/openpgl/include/openpgl/openpgl.h +++ b/openpgl/include/openpgl/openpgl.h @@ -5,29 +5,29 @@ #define OPENPGL_INLINE inline -//#define OPENPGL_DISABLE_ASSERTS +// #define OPENPGL_DISABLE_ASSERTS #ifndef OPENPGL_DISABLE_ASSERTS #include #define OPENPGL_ASSERT(cond) assert(cond); -//#define OPENPGL_ASSERT_MSG(cond, msg) SAssertEx(cond, msg); +// #define OPENPGL_ASSERT_MSG(cond, msg) SAssertEx(cond, msg); #else #define OPENPGL_ASSERT(cond) -//#define OPENPGL_ASSERT_MSG(cond, msg) +// #define OPENPGL_ASSERT_MSG(cond, msg) #endif -#include "defines.h" #include "common.h" +#include "defines.h" #if defined(OPENPGL_DIRECTION_COMPRESSION) || defined(OPENPGL_RADIANCE_COMPRESSION) #include "compression.h" #endif #include "data.h" -#include "region.h" -#include "samplestorage.h" -#include "pathsegmentstorage.h" #include "device.h" #include "field.h" #include "fieldstatistics.h" +#include "pathsegmentstorage.h" +#include "region.h" +#include "samplestorage.h" #include "surfacesamplingdistribution.h" #include "volumesamplingdistribution.h" #if defined(OPENPGL_IMAGE_SPACE_GUIDING_BUFFER) diff --git a/openpgl/include/openpgl/pathsegmentstorage.h b/openpgl/include/openpgl/pathsegmentstorage.h index 0b315fa..1d54bad 100644 --- a/openpgl/include/openpgl/pathsegmentstorage.h +++ b/openpgl/include/openpgl/pathsegmentstorage.h @@ -16,58 +16,61 @@ #include "samplestorage.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif #ifdef __cplusplus -struct PathSegmentStorage; + struct PathSegmentStorage; -struct PGLPathSegmentData; + struct PGLPathSegmentData; #else typedef ManagedObject Region; #endif -typedef PathSegmentStorage *PGLPathSegmentStorage; + typedef PathSegmentStorage *PGLPathSegmentStorage; -typedef PGLPathSegmentData *PGLPathSegment; + typedef PGLPathSegmentData *PGLPathSegment; -OPENPGL_CORE_INTERFACE PGLPathSegmentStorage pglNewPathSegmentStorage(bool trackZeroValueSamples); + OPENPGL_CORE_INTERFACE PGLPathSegmentStorage pglNewPathSegmentStorage(bool trackZeroValueSamples); -OPENPGL_CORE_INTERFACE void pglReleasePathSegmentStorage(PGLPathSegmentStorage pathSegmentStorage); + OPENPGL_CORE_INTERFACE void pglReleasePathSegmentStorage(PGLPathSegmentStorage pathSegmentStorage); -OPENPGL_CORE_INTERFACE void pglPathSegmentStorageReserve(PGLPathSegmentStorage pathSegmentStorage, size_t size); + OPENPGL_CORE_INTERFACE void pglPathSegmentStorageReserve(PGLPathSegmentStorage pathSegmentStorage, size_t size); -OPENPGL_CORE_INTERFACE void pglPathSegmentStorageClear(PGLPathSegmentStorage pathSegmentStorage); + OPENPGL_CORE_INTERFACE void pglPathSegmentStorageClear(PGLPathSegmentStorage pathSegmentStorage); -OPENPGL_CORE_INTERFACE void pglPathSegmentSetMaxDistance(PGLPathSegmentStorage pathSegmentStorage, float maxDistance); + OPENPGL_CORE_INTERFACE void pglPathSegmentSetMaxDistance(PGLPathSegmentStorage pathSegmentStorage, float maxDistance); -OPENPGL_CORE_INTERFACE float pglPathSegmentGetMaxDistance(PGLPathSegmentStorage pathSegmentStorage); + OPENPGL_CORE_INTERFACE float pglPathSegmentGetMaxDistance(PGLPathSegmentStorage pathSegmentStorage); -OPENPGL_CORE_INTERFACE int pglPathSegmentGetNumSegments(PGLPathSegmentStorage pathSegmentStorage); + OPENPGL_CORE_INTERFACE int pglPathSegmentGetNumSegments(PGLPathSegmentStorage pathSegmentStorage); -OPENPGL_CORE_INTERFACE int pglPathSegmentGetNumSamples(PGLPathSegmentStorage pathSegmentStorage); + OPENPGL_CORE_INTERFACE int pglPathSegmentGetNumSamples(PGLPathSegmentStorage pathSegmentStorage); -OPENPGL_CORE_INTERFACE int pglPathSegmentGetNumZeroValueSamples(PGLPathSegmentStorage pathSegmentStorage); + OPENPGL_CORE_INTERFACE int pglPathSegmentGetNumZeroValueSamples(PGLPathSegmentStorage pathSegmentStorage); -OPENPGL_CORE_INTERFACE size_t pglPathSegmentStoragePrepareSamples(PGLPathSegmentStorage pathSegmentStorage, const bool useNEEMiWeights = false, const bool guideDirectLight = false, const bool rrAffectsDirectContribution = true); + OPENPGL_CORE_INTERFACE size_t pglPathSegmentStoragePrepareSamples(PGLPathSegmentStorage pathSegmentStorage, const bool useNEEMiWeights = false, + const bool guideDirectLight = false, const bool rrAffectsDirectContribution = true); -OPENPGL_CORE_INTERFACE pgl_vec3f pglPathSegmentStorageCalculatePixelEstimate(PGLPathSegmentStorage pathSegmentStorage, const bool rrAffectsDirectContribution = true); + OPENPGL_CORE_INTERFACE pgl_vec3f pglPathSegmentStorageCalculatePixelEstimate(PGLPathSegmentStorage pathSegmentStorage, const bool rrAffectsDirectContribution = true); -OPENPGL_CORE_INTERFACE const PGLSampleData* pglPathSegmentStorageGetSamples(PGLPathSegmentStorage pathSegmentStorage, size_t &nSamples); + OPENPGL_CORE_INTERFACE const PGLSampleData *pglPathSegmentStorageGetSamples(PGLPathSegmentStorage pathSegmentStorage, size_t &nSamples); -OPENPGL_CORE_INTERFACE const PGLZeroValueSampleData* pglPathSegmentStorageGetZeroValueSamples(PGLPathSegmentStorage pathSegmentStorage, size_t &nSamples); + OPENPGL_CORE_INTERFACE const PGLZeroValueSampleData *pglPathSegmentStorageGetZeroValueSamples(PGLPathSegmentStorage pathSegmentStorage, size_t &nSamples); -OPENPGL_CORE_INTERFACE void pglPathSegmentStorageAddSample(PGLPathSegmentStorage pathSegmentStorage, PGLSampleData sample); + OPENPGL_CORE_INTERFACE void pglPathSegmentStorageAddSample(PGLPathSegmentStorage pathSegmentStorage, PGLSampleData sample); -OPENPGL_CORE_INTERFACE PGLPathSegmentData* pglPathSegmentStorageNextSegment(PGLPathSegmentStorage pathSegmentStorage); + OPENPGL_CORE_INTERFACE PGLPathSegmentData *pglPathSegmentStorageNextSegment(PGLPathSegmentStorage pathSegmentStorage); -OPENPGL_CORE_INTERFACE void pglPathSegmentStorageAddSegment(PGLPathSegmentStorage pathSegmentStorage, PGLPathSegmentData segment); + OPENPGL_CORE_INTERFACE void pglPathSegmentStorageAddSegment(PGLPathSegmentStorage pathSegmentStorage, PGLPathSegmentData segment); -OPENPGL_CORE_INTERFACE bool pglPathSegmentStorageValidateSamples(PGLPathSegmentStorage pathSegmentStorage); + OPENPGL_CORE_INTERFACE bool pglPathSegmentStorageValidateSamples(PGLPathSegmentStorage pathSegmentStorage); -OPENPGL_CORE_INTERFACE bool pglPathSegmentStorageValidateSegments(PGLPathSegmentStorage pathSegmentStorage); + OPENPGL_CORE_INTERFACE bool pglPathSegmentStorageValidateSegments(PGLPathSegmentStorage pathSegmentStorage); -OPENPGL_CORE_INTERFACE void pglPathSegmentStoragePropagateSamples(PGLPathSegmentStorage pathSegmentStorage, PGLSampleStorage sampleStorage, bool guideDirectLight = false, bool useNEEMiWeights = false, bool rrAffectsDirectContribution = true); + OPENPGL_CORE_INTERFACE void pglPathSegmentStoragePropagateSamples(PGLPathSegmentStorage pathSegmentStorage, PGLSampleStorage sampleStorage, bool guideDirectLight = false, + bool useNEEMiWeights = false, bool rrAffectsDirectContribution = true); #ifdef __cplusplus } // extern "C" diff --git a/openpgl/include/openpgl/region.h b/openpgl/include/openpgl/region.h index 4b891a7..e5528fa 100644 --- a/openpgl/include/openpgl/region.h +++ b/openpgl/include/openpgl/region.h @@ -7,17 +7,17 @@ #include "distribution.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif - #ifdef __cplusplus -struct Region; + struct Region; #else typedef ManagedObject Region; #endif -typedef Region *PGLRegion; + typedef Region *PGLRegion; #ifdef __cplusplus } // extern "C" diff --git a/openpgl/include/openpgl/samplestorage.h b/openpgl/include/openpgl/samplestorage.h index 4ce46f1..281af95 100644 --- a/openpgl/include/openpgl/samplestorage.h +++ b/openpgl/include/openpgl/samplestorage.h @@ -14,61 +14,62 @@ #endif #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif #ifdef __cplusplus -struct SampleStorage; + struct SampleStorage; -struct PGLSampleData; + struct PGLSampleData; #else typedef ManagedObject Region; #endif -typedef SampleStorage *PGLSampleStorage; + typedef SampleStorage *PGLSampleStorage; -typedef PGLSampleData PGLSampleData; + typedef PGLSampleData PGLSampleData; -OPENPGL_CORE_INTERFACE PGLSampleStorage pglNewSampleStorage(); + OPENPGL_CORE_INTERFACE PGLSampleStorage pglNewSampleStorage(); -OPENPGL_CORE_INTERFACE PGLSampleStorage pglNewSampleStorageFromFile(const char* sampleStorageFileName); + OPENPGL_CORE_INTERFACE PGLSampleStorage pglNewSampleStorageFromFile(const char *sampleStorageFileName); -OPENPGL_CORE_INTERFACE void pglReleaseSampleStorage(PGLSampleStorage sampleStorage); + OPENPGL_CORE_INTERFACE void pglReleaseSampleStorage(PGLSampleStorage sampleStorage); -OPENPGL_CORE_INTERFACE bool pglSampleStorageStoreToFile(PGLSampleStorage sampleStorage, const char* sampleStorageFileName); + OPENPGL_CORE_INTERFACE bool pglSampleStorageStoreToFile(PGLSampleStorage sampleStorage, const char *sampleStorageFileName); -OPENPGL_CORE_INTERFACE void pglSampleStorageAddSample(PGLSampleStorage sampleStorage, const PGLSampleData& sample); + OPENPGL_CORE_INTERFACE void pglSampleStorageAddSample(PGLSampleStorage sampleStorage, const PGLSampleData &sample); -OPENPGL_CORE_INTERFACE void pglSampleStorageAddSamples(PGLSampleStorage sampleStorage, const PGLSampleData* samples, size_t numSamples); + OPENPGL_CORE_INTERFACE void pglSampleStorageAddSamples(PGLSampleStorage sampleStorage, const PGLSampleData *samples, size_t numSamples); -OPENPGL_CORE_INTERFACE void pglSampleStorageAddZeroValueSample(PGLSampleStorage sampleStorage, const PGLZeroValueSampleData& sample); + OPENPGL_CORE_INTERFACE void pglSampleStorageAddZeroValueSample(PGLSampleStorage sampleStorage, const PGLZeroValueSampleData &sample); -OPENPGL_CORE_INTERFACE void pglSampleStorageAddZeroValueSamples(PGLSampleStorage sampleStorage, const PGLZeroValueSampleData* samples, size_t numSamples); + OPENPGL_CORE_INTERFACE void pglSampleStorageAddZeroValueSamples(PGLSampleStorage sampleStorage, const PGLZeroValueSampleData *samples, size_t numSamples); -OPENPGL_CORE_INTERFACE void pglSampleStorageReserve(PGLSampleStorage sampleStorage, const size_t sizeSurface, const size_t sizeVolume); + OPENPGL_CORE_INTERFACE void pglSampleStorageReserve(PGLSampleStorage sampleStorage, const size_t sizeSurface, const size_t sizeVolume); -OPENPGL_CORE_INTERFACE void pglSampleStorageClear(PGLSampleStorage sampleStorage); + OPENPGL_CORE_INTERFACE void pglSampleStorageClear(PGLSampleStorage sampleStorage); -OPENPGL_CORE_INTERFACE void pglSampleStorageClearSurface(PGLSampleStorage sampleStorage); + OPENPGL_CORE_INTERFACE void pglSampleStorageClearSurface(PGLSampleStorage sampleStorage); -OPENPGL_CORE_INTERFACE void pglSampleStorageClearVolume(PGLSampleStorage sampleStorage); + OPENPGL_CORE_INTERFACE void pglSampleStorageClearVolume(PGLSampleStorage sampleStorage); -OPENPGL_CORE_INTERFACE size_t pglSampleStorageGetSizeSurface(PGLSampleStorage sampleStorage); + OPENPGL_CORE_INTERFACE size_t pglSampleStorageGetSizeSurface(PGLSampleStorage sampleStorage); -OPENPGL_CORE_INTERFACE size_t pglSampleStorageGetSizeVolume(PGLSampleStorage sampleStorage); + OPENPGL_CORE_INTERFACE size_t pglSampleStorageGetSizeVolume(PGLSampleStorage sampleStorage); -OPENPGL_CORE_INTERFACE size_t pglSampleStorageGetSizeInvalidSurface(PGLSampleStorage sampleStorage); + OPENPGL_CORE_INTERFACE size_t pglSampleStorageGetSizeInvalidSurface(PGLSampleStorage sampleStorage); -OPENPGL_CORE_INTERFACE size_t pglSampleStorageGetSizeInvalidVolume(PGLSampleStorage sampleStorage); + OPENPGL_CORE_INTERFACE size_t pglSampleStorageGetSizeInvalidVolume(PGLSampleStorage sampleStorage); -OPENPGL_CORE_INTERFACE PGLSampleData pglSampleStorageGetSampleSurface(PGLSampleStorage sampleStorage, const int idx); + OPENPGL_CORE_INTERFACE PGLSampleData pglSampleStorageGetSampleSurface(PGLSampleStorage sampleStorage, const int idx); -OPENPGL_CORE_INTERFACE PGLSampleData pglSampleStorageGetSampleVolume(PGLSampleStorage sampleStorage, const int idx); + OPENPGL_CORE_INTERFACE PGLSampleData pglSampleStorageGetSampleVolume(PGLSampleStorage sampleStorage, const int idx); -OPENPGL_CORE_INTERFACE bool pglSampleStorageValidate(PGLSampleStorage sampleStorage); + OPENPGL_CORE_INTERFACE bool pglSampleStorageValidate(PGLSampleStorage sampleStorage); -OPENPGL_CORE_INTERFACE bool pglSampleStorageCompare(PGLSampleStorage sampleStorageA, PGLSampleStorage sampleStorageB); + OPENPGL_CORE_INTERFACE bool pglSampleStorageCompare(PGLSampleStorage sampleStorageA, PGLSampleStorage sampleStorageB); #ifdef __cplusplus } // extern "C" diff --git a/openpgl/include/openpgl/surfacesamplingdistribution.h b/openpgl/include/openpgl/surfacesamplingdistribution.h index 20e3029..ad922cb 100644 --- a/openpgl/include/openpgl/surfacesamplingdistribution.h +++ b/openpgl/include/openpgl/surfacesamplingdistribution.h @@ -3,50 +3,52 @@ #pragma once - #include "common.h" #include "region.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif #ifdef __cplusplus -struct SurfaceSamplingDistribution; + struct SurfaceSamplingDistribution; #else typedef ManagedObject SurfaceSamplingDistribution; #endif -typedef SurfaceSamplingDistribution *PGLSurfaceSamplingDistribution; + typedef SurfaceSamplingDistribution *PGLSurfaceSamplingDistribution; -OPENPGL_CORE_INTERFACE void pglReleaseSurfaceSamplingDistribution(PGLSurfaceSamplingDistribution surfaceSamplingDistribution); + OPENPGL_CORE_INTERFACE void pglReleaseSurfaceSamplingDistribution(PGLSurfaceSamplingDistribution surfaceSamplingDistribution); -OPENPGL_CORE_INTERFACE void pglSurfaceSamplingDistributionApplyCosineProduct(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f normal); + OPENPGL_CORE_INTERFACE void pglSurfaceSamplingDistributionApplyCosineProduct(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f normal); -OPENPGL_CORE_INTERFACE bool pglSurfaceSamplingDistributionSupportsApplyCosineProduct(PGLSurfaceSamplingDistribution surfaceSamplingDistribution); + OPENPGL_CORE_INTERFACE bool pglSurfaceSamplingDistributionSupportsApplyCosineProduct(PGLSurfaceSamplingDistribution surfaceSamplingDistribution); -OPENPGL_CORE_INTERFACE pgl_vec3f pglSurfaceSamplingDistributionSample(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_point2f sample); + OPENPGL_CORE_INTERFACE pgl_vec3f pglSurfaceSamplingDistributionSample(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_point2f sample); -OPENPGL_CORE_INTERFACE float pglSurfaceSamplingDistributionPDF(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f direction); + OPENPGL_CORE_INTERFACE float pglSurfaceSamplingDistributionPDF(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f direction); -OPENPGL_CORE_INTERFACE float pglSurfaceSamplingDistributionSamplePDF(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_point2f sample, pgl_vec3f &direction); + OPENPGL_CORE_INTERFACE float pglSurfaceSamplingDistributionSamplePDF(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_point2f sample, pgl_vec3f &direction); -OPENPGL_CORE_INTERFACE float pglSurfaceSamplingDistributionIncomingRadiancePDF(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f direction); + OPENPGL_CORE_INTERFACE float pglSurfaceSamplingDistributionIncomingRadiancePDF(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f direction); -OPENPGL_CORE_INTERFACE uint32_t pglSurfaceSamplingDistributionGetId(PGLSurfaceSamplingDistribution surfaceSamplingDistribution); + OPENPGL_CORE_INTERFACE uint32_t pglSurfaceSamplingDistributionGetId(PGLSurfaceSamplingDistribution surfaceSamplingDistribution); -OPENPGL_CORE_INTERFACE bool pglSurfaceSamplingDistributionValidate(PGLSurfaceSamplingDistribution surfaceSamplingDistribution); + OPENPGL_CORE_INTERFACE bool pglSurfaceSamplingDistributionValidate(PGLSurfaceSamplingDistribution surfaceSamplingDistribution); -OPENPGL_CORE_INTERFACE void pglSurfaceSamplingDistributionClear(PGLSurfaceSamplingDistribution surfaceSamplingDistribution); + OPENPGL_CORE_INTERFACE void pglSurfaceSamplingDistributionClear(PGLSurfaceSamplingDistribution surfaceSamplingDistribution); -OPENPGL_CORE_INTERFACE PGLRegion pglSurfaceSamplingGetRegion(PGLSurfaceSamplingDistribution surfaceSamplingDistribution); + OPENPGL_CORE_INTERFACE PGLRegion pglSurfaceSamplingGetRegion(PGLSurfaceSamplingDistribution surfaceSamplingDistribution); #ifdef OPENPGL_RADIANCE_CACHES -OPENPGL_CORE_INTERFACE pgl_vec3f pglSurfaceSamplingDistributionIncomingRadiance(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f direction, const bool directLightMIS); + OPENPGL_CORE_INTERFACE pgl_vec3f pglSurfaceSamplingDistributionIncomingRadiance(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f direction, + const bool directLightMIS); -OPENPGL_CORE_INTERFACE pgl_vec3f pglSurfaceSamplingDistributionIrradiance(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f normal, const bool directLightMIS); + OPENPGL_CORE_INTERFACE pgl_vec3f pglSurfaceSamplingDistributionIrradiance(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f normal, + const bool directLightMIS); -OPENPGL_CORE_INTERFACE pgl_vec3f pglSurfaceSamplingDistributionOutgoingRadiance(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f direction); + OPENPGL_CORE_INTERFACE pgl_vec3f pglSurfaceSamplingDistributionOutgoingRadiance(PGLSurfaceSamplingDistribution surfaceSamplingDistribution, pgl_vec3f direction); #endif #ifdef __cplusplus diff --git a/openpgl/include/openpgl/volumesamplingdistribution.h b/openpgl/include/openpgl/volumesamplingdistribution.h index 29fd48b..c4377c5 100644 --- a/openpgl/include/openpgl/volumesamplingdistribution.h +++ b/openpgl/include/openpgl/volumesamplingdistribution.h @@ -3,52 +3,55 @@ #pragma once - #include "common.h" #include "region.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif #ifdef __cplusplus -struct VolumeSamplingDistribution; + struct VolumeSamplingDistribution; #else typedef ManagedObject VolumeSamplingDistribution; #endif -typedef VolumeSamplingDistribution *PGLVolumeSamplingDistribution; + typedef VolumeSamplingDistribution *PGLVolumeSamplingDistribution; -OPENPGL_CORE_INTERFACE void pglReleaseVolumeSamplingDistribution(PGLVolumeSamplingDistribution VolumeSamplingDistribution); + OPENPGL_CORE_INTERFACE void pglReleaseVolumeSamplingDistribution(PGLVolumeSamplingDistribution VolumeSamplingDistribution); -OPENPGL_CORE_INTERFACE pgl_vec3f pglVolumeSamplingDistributionSample(PGLVolumeSamplingDistribution VolumeSamplingDistribution, pgl_point2f sample); + OPENPGL_CORE_INTERFACE pgl_vec3f pglVolumeSamplingDistributionSample(PGLVolumeSamplingDistribution VolumeSamplingDistribution, pgl_point2f sample); -OPENPGL_CORE_INTERFACE float pglVolumeSamplingDistributionPDF(PGLVolumeSamplingDistribution VolumeSamplingDistribution, pgl_vec3f direction); + OPENPGL_CORE_INTERFACE float pglVolumeSamplingDistributionPDF(PGLVolumeSamplingDistribution VolumeSamplingDistribution, pgl_vec3f direction); -OPENPGL_CORE_INTERFACE float pglVolumeSamplingDistributionSamplePDF(PGLVolumeSamplingDistribution VolumeSamplingDistribution, pgl_point2f sample, pgl_vec3f &direction); + OPENPGL_CORE_INTERFACE float pglVolumeSamplingDistributionSamplePDF(PGLVolumeSamplingDistribution VolumeSamplingDistribution, pgl_point2f sample, pgl_vec3f &direction); -OPENPGL_CORE_INTERFACE float pglVolumeSamplingDistributionIncomingRadiancePDF(PGLVolumeSamplingDistribution VolumeSamplingDistribution, pgl_vec3f direction); + OPENPGL_CORE_INTERFACE float pglVolumeSamplingDistributionIncomingRadiancePDF(PGLVolumeSamplingDistribution VolumeSamplingDistribution, pgl_vec3f direction); -OPENPGL_CORE_INTERFACE uint32_t pglVolumeSamplingDistributionGetId(PGLVolumeSamplingDistribution VolumeSamplingDistribution); + OPENPGL_CORE_INTERFACE uint32_t pglVolumeSamplingDistributionGetId(PGLVolumeSamplingDistribution VolumeSamplingDistribution); -OPENPGL_CORE_INTERFACE bool pglVolumeSamplingDistributionValidate(PGLVolumeSamplingDistribution VolumeSamplingDistribution); + OPENPGL_CORE_INTERFACE bool pglVolumeSamplingDistributionValidate(PGLVolumeSamplingDistribution VolumeSamplingDistribution); -OPENPGL_CORE_INTERFACE void pglVolumeSamplingDistributionClear(PGLVolumeSamplingDistribution VolumeSamplingDistribution); + OPENPGL_CORE_INTERFACE void pglVolumeSamplingDistributionClear(PGLVolumeSamplingDistribution VolumeSamplingDistribution); -OPENPGL_CORE_INTERFACE void pglVolumeSamplingDistributionApplySingleLobeHenyeyGreensteinProduct(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_vec3f dir, const float meanCosine); + OPENPGL_CORE_INTERFACE void pglVolumeSamplingDistributionApplySingleLobeHenyeyGreensteinProduct(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_vec3f dir, + const float meanCosine); -OPENPGL_CORE_INTERFACE bool pglVolumeSamplingDistributionSupportsApplySingleLobeHenyeyGreensteinProduct(PGLVolumeSamplingDistribution volumeSamplingDistribution); + OPENPGL_CORE_INTERFACE bool pglVolumeSamplingDistributionSupportsApplySingleLobeHenyeyGreensteinProduct(PGLVolumeSamplingDistribution volumeSamplingDistribution); -OPENPGL_CORE_INTERFACE PGLRegion pglVolumeSamplingGetRegion(PGLVolumeSamplingDistribution VolumeSamplingDistribution); + OPENPGL_CORE_INTERFACE PGLRegion pglVolumeSamplingGetRegion(PGLVolumeSamplingDistribution VolumeSamplingDistribution); #ifdef OPENPGL_RADIANCE_CACHES -OPENPGL_CORE_INTERFACE pgl_vec3f pglVolumeSamplingDistributionIncomingRadiance(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_vec3f direction, const bool directLightMIS); + OPENPGL_CORE_INTERFACE pgl_vec3f pglVolumeSamplingDistributionIncomingRadiance(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_vec3f direction, + const bool directLightMIS); -OPENPGL_CORE_INTERFACE pgl_vec3f pglVolumeSamplingDistributionOutgoingRadiance(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_vec3f direction); + OPENPGL_CORE_INTERFACE pgl_vec3f pglVolumeSamplingDistributionOutgoingRadiance(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_vec3f direction); -OPENPGL_CORE_INTERFACE pgl_vec3f pglVolumeSamplingDistributionInscatteredRadiance(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_vec3f direction, float g, const bool directLightMIS); + OPENPGL_CORE_INTERFACE pgl_vec3f pglVolumeSamplingDistributionInscatteredRadiance(PGLVolumeSamplingDistribution volumeSamplingDistribution, pgl_vec3f direction, float g, + const bool directLightMIS); -OPENPGL_CORE_INTERFACE pgl_vec3f pglVolumeSamplingDistributionFluence(PGLVolumeSamplingDistribution volumeSamplingDistribution, const bool directLightMIS); + OPENPGL_CORE_INTERFACE pgl_vec3f pglVolumeSamplingDistributionFluence(PGLVolumeSamplingDistribution volumeSamplingDistribution, const bool directLightMIS); #endif #ifdef __cplusplus diff --git a/openpgl/openpgl_common.h b/openpgl/openpgl_common.h index 4271272..2c561c4 100644 --- a/openpgl/openpgl_common.h +++ b/openpgl/openpgl_common.h @@ -9,159 +9,159 @@ #define USE_INTEGER_ARITHMETIC_STATS #define ONE_OVER_FOUR_PI 0.07957747154594767f -#define M_PI_F 3.14159265358979323846f /* pi */ +#define M_PI_F 3.14159265358979323846f /* pi */ +#include #include #include #include #include -#include -#include #include +#include -#if defined(__WIN32__) || ( defined(__MACOSX__) && !defined(__INTEL_COMPILER) ) +#if defined(__WIN32__) || (defined(__MACOSX__) && !defined(__INTEL_COMPILER)) -inline void sincosf(const float theta, float* sin, float* cos) +inline void sincosf(const float theta, float *sin, float *cos) { embree::sincosf(theta, sin, cos); } #elif defined(__MACOSX__) && defined(__INTEL_COMPILER) -inline void sincosf(const float theta, float* sin, float* cos) +inline void sincosf(const float theta, float *sin, float *cos) { - *sin = sinf(theta); + *sin = sinf(theta); *cos = cosf(theta); } - + #endif namespace openpgl { - template - void serializeFloatVectors(std::ostream& stream, const embree::vfloat *vectors) +template +void serializeFloatVectors(std::ostream &stream, const embree::vfloat *vectors) +{ + for (int i = 0; i < NumVectors; i++) { - for(int i = 0; i < NumVectors; i++) + for (int j = 0; j < VectorSize; j++) { - for(int j = 0; j < VectorSize; j++) - { - stream.write(reinterpret_cast(&vectors[i][j]), sizeof(float)); - } + stream.write(reinterpret_cast(&vectors[i][j]), sizeof(float)); } } +} - template - void deserializeFloatVectors(std::istream& stream, embree::vfloat *vectors) +template +void deserializeFloatVectors(std::istream &stream, embree::vfloat *vectors) +{ + for (int i = 0; i < NumVectors; i++) { - for(int i = 0; i < NumVectors; i++) + for (int j = 0; j < VectorSize; j++) { - for(int j = 0; j < VectorSize; j++) - { - stream.read(reinterpret_cast(&vectors[i][j]), sizeof(float)); - } + stream.read(reinterpret_cast(&vectors[i][j]), sizeof(float)); } } +} - template - void serializeVec2Vectors(std::ostream& stream, const embree::Vec2 > *vectors) +template +void serializeVec2Vectors(std::ostream &stream, const embree::Vec2 > *vectors) +{ + for (int i = 0; i < NumVectors; i++) { - for(int i = 0; i < NumVectors; i++) + for (int j = 0; j < VectorSize; j++) { - for(int j = 0; j < VectorSize; j++) - { - stream.write(reinterpret_cast(&vectors[i].x[j]), sizeof(float)); - } + stream.write(reinterpret_cast(&vectors[i].x[j]), sizeof(float)); } - for(int i = 0; i < NumVectors; i++) + } + for (int i = 0; i < NumVectors; i++) + { + for (int j = 0; j < VectorSize; j++) { - for(int j = 0; j < VectorSize; j++) - { - stream.write(reinterpret_cast(&vectors[i].y[j]), sizeof(float)); - } + stream.write(reinterpret_cast(&vectors[i].y[j]), sizeof(float)); } } +} - template - void deserializeVec2Vectors(std::istream& stream, embree::Vec2 > *vectors) +template +void deserializeVec2Vectors(std::istream &stream, embree::Vec2 > *vectors) +{ + for (int i = 0; i < NumVectors; i++) { - for(int i = 0; i < NumVectors; i++) + for (int j = 0; j < VectorSize; j++) { - for(int j = 0; j < VectorSize; j++) - { - stream.read(reinterpret_cast(&vectors[i].x[j]), sizeof(float)); - } + stream.read(reinterpret_cast(&vectors[i].x[j]), sizeof(float)); } - for(int i = 0; i < NumVectors; i++) + } + for (int i = 0; i < NumVectors; i++) + { + for (int j = 0; j < VectorSize; j++) { - for(int j = 0; j < VectorSize; j++) - { - stream.read(reinterpret_cast(&vectors[i].y[j]), sizeof(float)); - } + stream.read(reinterpret_cast(&vectors[i].y[j]), sizeof(float)); } } +} - template - void serializeVec3Vectors(std::ostream& stream, const embree::Vec3 > *vectors) +template +void serializeVec3Vectors(std::ostream &stream, const embree::Vec3 > *vectors) +{ + for (int i = 0; i < NumVectors; i++) { - for(int i = 0; i < NumVectors; i++) + for (int j = 0; j < VectorSize; j++) { - for(int j = 0; j < VectorSize; j++) - { - stream.write(reinterpret_cast(&vectors[i].x[j]), sizeof(float)); - } + stream.write(reinterpret_cast(&vectors[i].x[j]), sizeof(float)); } - for(int i = 0; i < NumVectors; i++) + } + for (int i = 0; i < NumVectors; i++) + { + for (int j = 0; j < VectorSize; j++) { - for(int j = 0; j < VectorSize; j++) - { - stream.write(reinterpret_cast(&vectors[i].y[j]), sizeof(float)); - } + stream.write(reinterpret_cast(&vectors[i].y[j]), sizeof(float)); } - for(int i = 0; i < NumVectors; i++) + } + for (int i = 0; i < NumVectors; i++) + { + for (int j = 0; j < VectorSize; j++) { - for(int j = 0; j < VectorSize; j++) - { - stream.write(reinterpret_cast(&vectors[i].z[j]), sizeof(float)); - } + stream.write(reinterpret_cast(&vectors[i].z[j]), sizeof(float)); } } +} - template - void deserializeVec3Vectors(std::istream& stream, embree::Vec3 > *vectors) +template +void deserializeVec3Vectors(std::istream &stream, embree::Vec3 > *vectors) +{ + for (int i = 0; i < NumVectors; i++) { - for(int i = 0; i < NumVectors; i++) + for (int j = 0; j < VectorSize; j++) { - for(int j = 0; j < VectorSize; j++) - { - stream.read(reinterpret_cast(&vectors[i].x[j]), sizeof(float)); - } + stream.read(reinterpret_cast(&vectors[i].x[j]), sizeof(float)); } - for(int i = 0; i < NumVectors; i++) + } + for (int i = 0; i < NumVectors; i++) + { + for (int j = 0; j < VectorSize; j++) { - for(int j = 0; j < VectorSize; j++) - { - stream.read(reinterpret_cast(&vectors[i].y[j]), sizeof(float)); - } + stream.read(reinterpret_cast(&vectors[i].y[j]), sizeof(float)); } - for(int i = 0; i < NumVectors; i++) + } + for (int i = 0; i < NumVectors; i++) + { + for (int j = 0; j < VectorSize; j++) { - for(int j = 0; j < VectorSize; j++) - { - stream.read(reinterpret_cast(&vectors[i].z[j]), sizeof(float)); - } + stream.read(reinterpret_cast(&vectors[i].z[j]), sizeof(float)); } } } +} // namespace openpgl namespace openpgl { - template -__forceinline embree::vfloat4 vshift_left(const embree::vfloat4& v) +template +__forceinline embree::vfloat4 vshift_left(const embree::vfloat4 &v) { return embree::asFloat(_mm_slli_si128(asInt(v), imm)); } -__forceinline embree::vfloat4 vinclusive_prefix_sum(const embree::vfloat4& v) +__forceinline embree::vfloat4 vinclusive_prefix_sum(const embree::vfloat4 &v) { embree::vfloat4 x = v; x += vshift_left<4>(x); @@ -171,13 +171,13 @@ __forceinline embree::vfloat4 vinclusive_prefix_sum(const embree::vfloat4& v) //__forceinline vint8 asInt (const vfloat8& a) { return _mm256_castps_si256(a); } #if defined(__AVX__) -template -__forceinline embree::vfloat8 vshift_left(const embree::vfloat8& v) +template +__forceinline embree::vfloat8 vshift_left(const embree::vfloat8 &v) { return embree::asFloat(_mm256_slli_si256(asInt(v), imm)); } -__forceinline embree::vfloat8 vinclusive_prefix_sum(const embree::vfloat8& v) +__forceinline embree::vfloat8 vinclusive_prefix_sum(const embree::vfloat8 &v) { embree::vfloat8 x = v; x += vshift_left<4>(x); @@ -189,19 +189,20 @@ __forceinline embree::vfloat8 vinclusive_prefix_sum(const embree::vfloat8& v) #if defined(__AVX512F__) template -__m512i _mm512_slli_si512 ( __m512i x) { - const __m512i ZERO = _mm512_setzero_si512 (); - return _mm512_alignr_epi32 (x , ZERO , 16 - k ); +__m512i _mm512_slli_si512(__m512i x) +{ + const __m512i ZERO = _mm512_setzero_si512(); + return _mm512_alignr_epi32(x, ZERO, 16 - k); } -template -__forceinline embree::vfloat16 vshift_left(const embree::vfloat16& v) +template +__forceinline embree::vfloat16 vshift_left(const embree::vfloat16 &v) { return embree::asFloat(_mm512_slli_si512(asInt(v))); } // From the arxiv paper: Parallel Prefix Sum with SIMD -__forceinline embree::vfloat16 vinclusive_prefix_sum(const embree::vfloat16& v) +__forceinline embree::vfloat16 vinclusive_prefix_sum(const embree::vfloat16 &v) { embree::vfloat16 x = v; x += vshift_left<1>(x); @@ -211,148 +212,160 @@ __forceinline embree::vfloat16 vinclusive_prefix_sum(const embree::vfloat16& v) return x; } #endif -} +} // namespace openpgl namespace openpgl { - inline void* alignedMalloc(size_t size, size_t align) - { +inline void *alignedMalloc(size_t size, size_t align) +{ if (size == 0) - return nullptr; + return nullptr; - assert((align & (align-1)) == 0); - void* ptr = _mm_malloc(size,align); + assert((align & (align - 1)) == 0); + void *ptr = _mm_malloc(size, align); if (size != 0 && ptr == nullptr) - throw std::bad_alloc(); + throw std::bad_alloc(); return ptr; - } +} - inline void alignedFree(void* ptr) - { +inline void alignedFree(void *ptr) +{ if (ptr) - _mm_free(ptr); - } + _mm_free(ptr); } - -#define OPENPGL_ALIGNED_STRUCT_(align) \ - void* operator new(size_t size) { return openpgl::alignedMalloc(size,align); } \ - void operator delete(void* ptr) { openpgl::alignedFree(ptr); } \ - void* operator new[](size_t size) { return openpgl::alignedMalloc(size,align); } \ - void operator delete[](void* ptr) { openpgl::alignedFree(ptr); } +} // namespace openpgl + +#define OPENPGL_ALIGNED_STRUCT_(align) \ + void *operator new(size_t size) \ + { \ + return openpgl::alignedMalloc(size, align); \ + } \ + void operator delete(void *ptr) \ + { \ + openpgl::alignedFree(ptr); \ + } \ + void *operator new[](size_t size) \ + { \ + return openpgl::alignedMalloc(size, align); \ + } \ + void operator delete[](void *ptr) \ + { \ + openpgl::alignedFree(ptr); \ + } namespace openpgl { - typedef embree::Vec2 Vector2; - typedef embree::Vec3 Vector3; - typedef embree::Vec2 Point2; - typedef embree::Vec3 Point3; +typedef embree::Vec2 Vector2; +typedef embree::Vec3 Vector3; +typedef embree::Vec2 Point2; +typedef embree::Vec3 Point3; - typedef embree::Vec3 Point3i; - typedef embree::Vec3 Vector3i; +typedef embree::Vec3 Point3i; +typedef embree::Vec3 Vector3i; - typedef embree::BBox BBox; - typedef embree::BBox BBoxi; +typedef embree::BBox BBox; +typedef embree::BBox BBoxi; - inline float dot(Vector2 &a, Vector2 &b) - { - return embree::dot(a, b); - } +inline float dot(Vector2 &a, Vector2 &b) +{ + return embree::dot(a, b); +} - inline float dot(Vector3 &a, Vector3 &b) - { - return embree::dot(a, b); - } +inline float dot(Vector3 &a, Vector3 &b) +{ + return embree::dot(a, b); } +} // namespace openpgl -//#define OPENPGL_DISABLE_ASSERTS +// #define OPENPGL_DISABLE_ASSERTS #ifndef OPENPGL_DISABLE_ASSERTS #include #define OPENPGL_ASSERT(cond) assert(cond); -//#define OPENPGL_ASSERT_MSG(cond, msg) SAssertEx(cond, msg); +// #define OPENPGL_ASSERT_MSG(cond, msg) SAssertEx(cond, msg); #else #define OPENPGL_ASSERT(cond) -//#define OPENPGL_ASSERT_MSG(cond, msg) +// #define OPENPGL_ASSERT_MSG(cond, msg) #endif namespace openpgl { - template - inline float sum( const embree::vfloat &v) +template +inline float sum(const embree::vfloat &v) +{ + float sum = 0.0f; + for (int i = 0; i < VecSize; i++) { - float sum = 0.0f; - for ( int i = 0; i < VecSize; i++) - { - sum += v[i]; - } - return sum; + sum += v[i]; } + return sum; +} +inline Vector2 toSphericalCoordinates(const Vector3 &v) +{ + Vector2 result(std::acos(v.z), std::atan2(v.y, v.x)); + if (result.y < 0) + result.y += 2.0f * M_PI_F; + return result; +} - inline Vector2 toSphericalCoordinates(const Vector3 &v) { - Vector2 result( - std::acos(v.z), - std::atan2(v.y, v.x) - ); - if (result.y < 0) - result.y += 2.0f*M_PI_F; - return result; - } +inline Vector3 sphericalDirection(const float &cosTheta, const float &sinTheta, const float &cosPhi, const float &sinPhi) +{ + return Vector3(sinTheta * cosPhi, sinTheta * sinPhi, cosTheta); +}; - inline Vector3 sphericalDirection(const float &cosTheta, const float &sinTheta, const float &cosPhi, const float &sinPhi) - { - return Vector3( sinTheta * cosPhi, - sinTheta * sinPhi, - cosTheta); - }; +inline Vector3 sphericalDirection(const float &theta, const float &phi) +{ + const float cosTheta = std::cos(theta); + const float sinTheta = std::sin(theta); + const float cosPhi = std::cos(phi); + const float sinPhi = std::sin(phi); - inline Vector3 sphericalDirection(const float &theta, const float &phi) - { - const float cosTheta = std::cos(theta); - const float sinTheta = std::sin(theta); - const float cosPhi = std::cos(phi); - const float sinPhi = std::sin(phi); - - return sphericalDirection(cosTheta, sinTheta, cosPhi, sinPhi); - }; - - inline Vector3 squareToUniformSphere(const Vector2 sample){ - float z = 1.0f - 2.0f * sample.y; - float r = std::sqrt(std::max(0.f,(1.0f - z*z))); - float sinPhi, cosPhi; - sincosf(2.0f * M_PI_F * sample.x, &sinPhi, &cosPhi); - return Vector3(r * cosPhi, r * sinPhi, z); - } + return sphericalDirection(cosTheta, sinTheta, cosPhi, sinPhi); +}; +inline Vector3 squareToUniformSphere(const Vector2 sample) +{ + float z = 1.0f - 2.0f * sample.y; + float r = std::sqrt(std::max(0.f, (1.0f - z * z))); + float sinPhi, cosPhi; + sincosf(2.0f * M_PI_F * sample.x, &sinPhi, &cosPhi); + return Vector3(r * cosPhi, r * sinPhi, z); } +} // namespace openpgl + #include namespace openpgl { - class Timer { - private: - using clock = std::chrono::high_resolution_clock; - using time_point = clock::time_point; - - public: - Timer() { - reset(); - } +class Timer +{ + private: + using clock = std::chrono::high_resolution_clock; + using time_point = clock::time_point; - void reset() { - start = clock::now(); - } + public: + Timer() + { + reset(); + } - double elapsed() { - time_point end = clock::now(); - std::chrono::duration diff = end - start; - return diff.count(); - } + void reset() + { + start = clock::now(); + } + + double elapsed() + { + time_point end = clock::now(); + std::chrono::duration diff = end - start; + return diff.count(); + } - private: - time_point start; - }; -} \ No newline at end of file + private: + time_point start; +}; +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/spatial/IRegion.h b/openpgl/spatial/IRegion.h index 74df38f..c6f12b5 100644 --- a/openpgl/spatial/IRegion.h +++ b/openpgl/spatial/IRegion.h @@ -8,15 +8,15 @@ namespace openpgl { - - struct IRegion - { - virtual ~IRegion(){}; + +struct IRegion +{ + virtual ~IRegion(){}; #ifdef OPENPGL_RADIANCE_CACHES - virtual Vector3 getOutgoingRadiance(const Vector3 dir) const = 0; + virtual Vector3 getOutgoingRadiance(const Vector3 dir) const = 0; #endif - public: - bool valid{true}; - }; -} \ No newline at end of file + public: + bool valid{true}; +}; +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/spatial/KNN.h b/openpgl/spatial/KNN.h index 1506ed2..5d694d4 100644 --- a/openpgl/spatial/KNN.h +++ b/openpgl/spatial/KNN.h @@ -6,14 +6,13 @@ // Nearest neighbor queries /* include nanoflann API */ -#include -#include -#include - #include - #include +#include +#include +#include + #define NUM_KNN 4 #define NUM_KNN_NEIGHBOURS 8 #define DEBUG_SAMPLE_APPROXIMATE_CLOSEST_REGION_IDX 0 @@ -23,7 +22,8 @@ namespace openpgl { -inline uint32_t draw(float* sample, uint32_t size) { +inline uint32_t draw(float *sample, uint32_t size) +{ size = std::min(NUM_KNN, size); uint32_t selected = *sample * size; *sample = (*sample - float(selected) / size) * size; @@ -31,26 +31,25 @@ inline uint32_t draw(float* sample, uint32_t size) { return std::min(selected, size - 1); } -template -uint32_t sampleApproximateClosestRegionIdxRef(const RegionNeighbours &nh, const openpgl::Point3 &p, float sample) { +template +uint32_t sampleApproximateClosestRegionIdxRef(const RegionNeighbours &nh, const openpgl::Point3 &p, float sample) +{ uint32_t selected = draw(&sample, nh.size); using E = std::pair; E candidates[NUM_KNN_NEIGHBOURS]; - for (int i = 0; i < nh.size; i++) { + for (int i = 0; i < nh.size; i++) + { auto tup = nh.get(i); const uint32_t primID = std::get<0>(tup); - const float - xd = std::get<1>(tup) - p.x, - yd = std::get<2>(tup) - p.y, - zd = std::get<3>(tup) - p.z; + const float xd = std::get<1>(tup) - p.x, yd = std::get<2>(tup) - p.y, zd = std::get<3>(tup) - p.z; float d = xd * xd + yd * yd + zd * zd; // we use the three least significant bits of the mantissa to store the array ids, // so we have to do the same to get the same results uint32_t mask = (1 << 3) - 1; - uint32_t *df = (uint32_t*)&d; + uint32_t *df = (uint32_t *)&d; *df = (*df & ~mask) | (i & mask); candidates[i] = {primID, d}; @@ -62,76 +61,85 @@ uint32_t sampleApproximateClosestRegionIdxRef(const RegionNeighbours &nh, const return candidates[selected].first; } -template -struct RegionNeighbours { }; +template +struct RegionNeighbours +{}; - -template<> +template <> struct RegionNeighbours<4> { - embree::vuint<4> ids[2]; - embree::Vec3 > points[2]; + embree::vuint<4> ids[2]; + embree::Vec3> points[2]; uint32_t size; - inline void set(uint32_t i, uint32_t id, float x, float y, float z) { + inline void set(uint32_t i, uint32_t id, float x, float y, float z) + { ids[i / 4][i % 4] = id; - points[i / 4].x[i % 4] = x; - points[i / 4].y[i % 4] = y; - points[i / 4].z[i % 4] = z; + points[i / 4].x[i % 4] = x; + points[i / 4].y[i % 4] = y; + points[i / 4].z[i % 4] = z; } - inline std::tuple get(uint32_t i) const { - return { ids[i / 4][i % 4], points[i / 4].x[i % 4], points[i / 4].y[i % 4], points[i / 4].z[i % 4] }; + inline std::tuple get(uint32_t i) const + { + return {ids[i / 4][i % 4], points[i / 4].x[i % 4], points[i / 4].y[i % 4], points[i / 4].z[i % 4]}; } - inline embree::vfloat<4> prepare(const uint32_t i, const embree::Vec3< embree::vfloat<4> > &p) const { - // While we only need the first two mantissa bits here, + inline embree::vfloat<4> prepare(const uint32_t i, const embree::Vec3> &p) const + { + // While we only need the first two mantissa bits here, // we want to keep the output consistent with the 8- and 16-wide implementation const embree::vfloat<4> ids = asFloat(embree::vint<4>(0, 1, 2, 3) + 4 * i); const embree::vfloat<4> mask = asFloat(embree::vint<4>(~7)); const embree::Vec3> d = points[i] - p; - embree::vfloat<4> distances = embree::dot(d,d); - distances = distances&mask | ids; + embree::vfloat<4> distances = embree::dot(d, d); + distances = distances & mask | ids; distances = select(this->ids[i] != ~0, distances, embree::vfloat<4>(std::numeric_limits::infinity())); return sort_ascending(distances); } - inline uint32_t sampleApproximateClosestRegionIdx(const openpgl::Point3 &p, float* sample) const { + inline uint32_t sampleApproximateClosestRegionIdx(const openpgl::Point3 &p, float *sample) const + { uint32_t selected = draw(sample, size); - const embree::Vec3< embree::vfloat<4> > _p(p[0], p[1], p[2]); + const embree::Vec3> _p(p[0], p[1], p[2]); const embree::vfloat<4> d0 = prepare(0, _p); const embree::vfloat<4> d1 = prepare(1, _p); uint32_t i0 = 0, i1 = 0; - for (uint32_t i = 0; i < selected; i++) { - if (d0[i0] < d1[i1]) i0++; - else i1++; + for (uint32_t i = 0; i < selected; i++) + { + if (d0[i0] < d1[i1]) + i0++; + else + i1++; } - if (d0[i0] < d1[i1]) return ids[0][asInt(d0)[i0] & 3]; - else return ids[1][asInt(d1)[i1] & 3]; + if (d0[i0] < d1[i1]) + return ids[0][asInt(d0)[i0] & 3]; + else + return ids[1][asInt(d1)[i1] & 3]; } - inline uint32_t sampleApproximateClosestRegionIdxIS(const openpgl::Point3 &p, float* sample) const { - - const embree::Vec3< embree::vfloat<4>> _p(p[0], p[1], p[2]); + inline uint32_t sampleApproximateClosestRegionIdxIS(const openpgl::Point3 &p, float *sample) const + { + const embree::Vec3> _p(p[0], p[1], p[2]); embree::Vec3> d[2]; d[0] = this->points[0] - _p; d[1] = this->points[1] - _p; embree::vfloat<4> dist[2]; - dist[0] = embree::dot(d[0],d[0]); - dist[1] = embree::dot(d[1],d[1]); + dist[0] = embree::dot(d[0], d[0]); + dist[1] = embree::dot(d[1], d[1]); const float maxDist = std::max(embree::reduce_max(dist[0]), embree::reduce_max(dist[1])); const float sigma = std::sqrt(maxDist) / 4.0f; dist[0] = embree::fastapprox::exp(-0.5f * dist[0] / (sigma * sigma)); dist[1] = embree::fastapprox::exp(-0.5f * dist[1] / (sigma * sigma)); -#ifdef KNN_IS_SIMD - embree::vfloat<4> cdfs[2]; +#ifdef KNN_IS_SIMD + embree::vfloat<4> cdfs[2]; cdfs[0] = vinclusive_prefix_sum(dist[0]); cdfs[1] = vinclusive_prefix_sum(dist[1]); @@ -140,13 +148,13 @@ struct RegionNeighbours<4> const float sumDist = sumDist0 + sumDist1; float searched = *sample * sumDist; size_t idx = 0; - if(searched > sumDist0) + if (searched > sumDist0) { searched -= sumDist0; idx = 1; } const size_t sidx = embree::select_min(cdfs[idx] >= searched, cdfs[idx]); - const float sumCDF = sidx > 0 ? cdfs[idx][sidx-1] : 0.f; + const float sumCDF = sidx > 0 ? cdfs[idx][sidx - 1] : 0.f; *sample = std::min(1 - FLT_EPSILON, (searched - sumCDF) / dist[idx][sidx]); return this->ids[idx][sidx]; #else @@ -157,20 +165,21 @@ struct RegionNeighbours<4> size_t idx = 0; float sumCDF = 0.0f; float searched = *sample * sumDist; - if(searched > sumDist0) + if (searched > sumDist0) { sumCDF = sumDist0; idx = 1; } float cdf = 0.f; size_t sidx = 0; - while(true){ + while (true) + { cdf = dist[idx][sidx]; - if(sumCDF+cdf >= searched || sidx+1 >=4) + if (sumCDF + cdf >= searched || sidx + 1 >= 4) { break; - } - else + } + else { sumCDF += cdf; sidx++; @@ -184,45 +193,49 @@ struct RegionNeighbours<4> }; #if defined(__AVX__) -template<> +template <> struct RegionNeighbours<8> { - embree::vuint<8> ids; - embree::Vec3 > points; + embree::vuint<8> ids; + embree::Vec3> points; uint32_t size; - inline void set(uint32_t i, uint32_t id, float x, float y, float z) { + inline void set(uint32_t i, uint32_t id, float x, float y, float z) + { ids[i] = id; - points.x[i] = x; - points.y[i] = y; - points.z[i] = z; + points.x[i] = x; + points.y[i] = y; + points.z[i] = z; } - inline std::tuple get(uint32_t i) const { - return { ids[i], points.x[i], points.y[i], points.z[i] }; + inline std::tuple get(uint32_t i) const + { + return {ids[i], points.x[i], points.y[i], points.z[i]}; } - inline uint32_t sampleApproximateClosestRegionIdx(const openpgl::Point3 &p, float* sample) const { + inline uint32_t sampleApproximateClosestRegionIdx(const openpgl::Point3 &p, float *sample) const + { uint32_t selected = draw(sample, size); const embree::vfloat<8> ids = asFloat(embree::vint<8>(0, 1, 2, 3, 4, 5, 6, 7)); const embree::vfloat<8> mask = asFloat(embree::vint<8>(~7)); - const embree::Vec3< embree::vfloat<8> > _p(p[0], p[1], p[2]); + const embree::Vec3> _p(p[0], p[1], p[2]); const embree::Vec3> d = points - _p; - embree::vfloat<8> distances = embree::dot(d,d); - distances = distances&mask | ids; + embree::vfloat<8> distances = embree::dot(d, d); + distances = distances & mask | ids; distances = select(this->ids != ~0, distances, embree::vfloat<8>(std::numeric_limits::infinity())); distances = sort_ascending(distances); return this->ids[asInt(distances)[selected] & 7]; } - inline uint32_t sampleApproximateClosestRegionIdxIS(const openpgl::Point3 &p, float* sample) const { - const embree::Vec3< embree::vfloat<8>> _p(p[0], p[1], p[2]); + inline uint32_t sampleApproximateClosestRegionIdxIS(const openpgl::Point3 &p, float *sample) const + { + const embree::Vec3> _p(p[0], p[1], p[2]); embree::Vec3> d; d = this->points - _p; - embree::vfloat<8> dist = embree::dot(d,d); + embree::vfloat<8> dist = embree::dot(d, d); const float maxDist = embree::reduce_max(dist); const float sigma = std::sqrt(maxDist) / 4.0f; dist = embree::fastapprox::exp(-0.5f * dist / (sigma * sigma)); @@ -232,7 +245,7 @@ struct RegionNeighbours<8> const float sumDist = cdfs[7]; const float searched = *sample * sumDist; const size_t idx = embree::select_min(cdfs >= searched, cdfs); - const float sumCDF = idx > 0 ? cdfs[idx-1] : 0.f; + const float sumCDF = idx > 0 ? cdfs[idx - 1] : 0.f; *sample = std::min(1 - FLT_EPSILON, (searched - sumCDF) / dist[idx]); return this->ids[idx]; #else @@ -242,13 +255,14 @@ struct RegionNeighbours<8> float sumCDF = 0.0f; float searched = *sample * sumDist; float cdf = 0.f; - while(true){ + while (true) + { cdf = dist[idx]; - if(sumCDF+cdf >= searched || idx+1 >=4) + if (sumCDF + cdf >= searched || idx + 1 >= 4) { break; - } - else + } + else { sumCDF += cdf; idx++; @@ -261,17 +275,18 @@ struct RegionNeighbours<8> } }; -template<> -struct RegionNeighbours<16>: public RegionNeighbours<8> { }; +template <> +struct RegionNeighbours<16> : public RegionNeighbours<8> +{}; #endif -template +template struct KNearestRegionsSearchTree { struct Point { OPENPGL_ALIGNED_STRUCT_(16) - embree::Vec3fa p; //!< position + embree::Vec3fa p; //!< position }; struct Neighbour @@ -279,7 +294,10 @@ struct KNearestRegionsSearchTree unsigned int primID; float d; - bool operator<(Neighbour const& n1) const { return d < n1.d; } + bool operator<(Neighbour const &n1) const + { + return d < n1.d; + } }; using This = KNearestRegionsSearchTree; @@ -290,7 +308,7 @@ struct KNearestRegionsSearchTree KNearestRegionsSearchTree() = default; - KNearestRegionsSearchTree(const KNearestRegionsSearchTree&) = delete; + KNearestRegionsSearchTree(const KNearestRegionsSearchTree &) = delete; ~KNearestRegionsSearchTree() { @@ -298,7 +316,7 @@ struct KNearestRegionsSearchTree alignedFree(neighbours); } - template + template void buildRegionSearchTree(const TRegionStorageContainer ®ionStorage) { num_points = regionStorage.size(); @@ -306,12 +324,12 @@ struct KNearestRegionsSearchTree { alignedFree(points); } - points = (Point*) alignedMalloc(num_points*sizeof(Point), 32); + points = (Point *)alignedMalloc(num_points * sizeof(Point), 32); for (size_t i = 0; i < num_points; i++) { - const auto& region = regionStorage[i].first; - const openpgl::SampleStatistics& combinedStats = region.sampleStatistics; + const auto ®ion = regionStorage[i].first; + const openpgl::SampleStatistics &combinedStats = region.sampleStatistics; const openpgl::Point3 distributionPivot = combinedStats.mean; points[i].p = embree::Vec3f(distributionPivot[0], distributionPivot[1], distributionPivot[2]); } @@ -330,55 +348,51 @@ struct KNearestRegionsSearchTree { alignedFree(neighbours); } - neighbours = (RN*) alignedMalloc(num_points*sizeof(RN), 32); + neighbours = (RN *)alignedMalloc(num_points * sizeof(RN), 32); - tbb::parallel_for( tbb::blocked_range(0,num_points), [&](tbb::blocked_range r) - { - for (int n = r.begin(); nknnSearch(&query_pt[0], num_results, &ret_index[0], &ret_dist_sqr[0]); - - bool selfIsIn = false; - - auto &nh = neighbours[n]; - nh.size = num_results; - int i = 0; - for (; i < num_results; i++) { - size_t idx = ret_index[i]; - selfIsIn = selfIsIn || idx == n; - nh.set(i, idx, - points[idx].p.x, - points[idx].p.y, - points[idx].p.z - ); - } - for (; i < NUM_KNN_NEIGHBOURS; i++) + tbb::parallel_for(tbb::blocked_range(0, num_points), [&](tbb::blocked_range r) { + for (int n = r.begin(); n < r.end(); ++n) { - nh.set(i, ~0, 0, 0, 0); - } + Point &point = points[n]; + + const float query_pt[3] = {point.p.x, point.p.y, point.p.z}; - OPENPGL_ASSERT(selfIsIn); + size_t num_results = NUM_KNN_NEIGHBOURS; + unsigned int ret_index[NUM_KNN_NEIGHBOURS]; + float ret_dist_sqr[NUM_KNN_NEIGHBOURS]; + + num_results = index->knnSearch(&query_pt[0], num_results, &ret_index[0], &ret_dist_sqr[0]); + + bool selfIsIn = false; + + auto &nh = neighbours[n]; + nh.size = num_results; + int i = 0; + for (; i < num_results; i++) + { + size_t idx = ret_index[i]; + selfIsIn = selfIsIn || idx == n; + nh.set(i, idx, points[idx].p.x, points[idx].p.y, points[idx].p.z); + } + for (; i < NUM_KNN_NEIGHBOURS; i++) + { + nh.set(i, ~0, 0, 0, 0); + } + + OPENPGL_ASSERT(selfIsIn); #ifdef OPENPGL_SHOW_PRINT_OUTS - if (!selfIsIn) - { - std::cout << "No closest region found" << std::endl; - } + if (!selfIsIn) + { + std::cout << "No closest region found" << std::endl; + } #endif - } + } }); _isBuildNeighbours = true; } - uint32_t sampleClosestRegionIdx(const openpgl::Point3 &p, float* sample) const + uint32_t sampleClosestRegionIdx(const openpgl::Point3 &p, float *sample) const { OPENPGL_ASSERT(_isBuild); @@ -401,7 +415,8 @@ struct KNearestRegionsSearchTree return ret_index[draw(sample, num_results)]; } - uint32_t sampleApproximateClosestRegionIdx(unsigned int regionIdx, const openpgl::Point3 &p, float* sample) const { + uint32_t sampleApproximateClosestRegionIdx(unsigned int regionIdx, const openpgl::Point3 &p, float *sample) const + { OPENPGL_ASSERT(_isBuildNeighbours); #if DEBUG_SAMPLE_APPROXIMATE_CLOSEST_REGION_IDX @@ -415,7 +430,8 @@ struct KNearestRegionsSearchTree return out; } - uint32_t sampleApproximateClosestRegionIdxIS(unsigned int regionIdx, const openpgl::Point3 &p, float* sample) const { + uint32_t sampleApproximateClosestRegionIdxIS(unsigned int regionIdx, const openpgl::Point3 &p, float *sample) const + { OPENPGL_ASSERT(_isBuildNeighbours); uint32_t out = neighbours[regionIdx].sampleApproximateClosestRegionIdxIS(p, sample); return out; @@ -436,29 +452,29 @@ struct KNearestRegionsSearchTree return num_points; } - void serialize(std::ostream& stream) const + void serialize(std::ostream &stream) const { - stream.write(reinterpret_cast(&_isBuild), sizeof(bool)); - if(_isBuild) + stream.write(reinterpret_cast(&_isBuild), sizeof(bool)); + if (_isBuild) { - stream.write(reinterpret_cast(&num_points), sizeof(uint32_t)); + stream.write(reinterpret_cast(&num_points), sizeof(uint32_t)); for (uint32_t n = 0; n < num_points; n++) { - stream.write(reinterpret_cast(&points[n]), sizeof(Point)); + stream.write(reinterpret_cast(&points[n]), sizeof(Point)); } } } void reset() { - if(points) + if (points) { alignedFree(points); points = nullptr; num_points = 0; } - if(neighbours) + if (neighbours) { alignedFree(neighbours); neighbours = nullptr; @@ -468,17 +484,17 @@ struct KNearestRegionsSearchTree _isBuild = false; } - void deserialize(std::istream& stream) + void deserialize(std::istream &stream) { - stream.read(reinterpret_cast(&_isBuild), sizeof(bool)); - if(_isBuild) + stream.read(reinterpret_cast(&_isBuild), sizeof(bool)); + if (_isBuild) { - stream.read(reinterpret_cast(&num_points), sizeof(uint32_t)); - points = (Point*) alignedMalloc(num_points*sizeof(Point), 32); + stream.read(reinterpret_cast(&num_points), sizeof(uint32_t)); + points = (Point *)alignedMalloc(num_points * sizeof(Point), 32); for (uint32_t n = 0; n < num_points; n++) { Point p; - stream.read(reinterpret_cast(&p), sizeof(Point)); + stream.read(reinterpret_cast(&p), sizeof(Point)); points[n] = p; } @@ -507,22 +523,21 @@ struct KNearestRegionsSearchTree } template - bool kdtree_get_bbox(BBOX& /*bb*/) const + bool kdtree_get_bbox(BBOX & /*bb*/) const { return false; } -private: - - Point* points = nullptr; - uint32_t num_points {0}; + private: + Point *points = nullptr; + uint32_t num_points{0}; std::unique_ptr index; - RN* neighbours = nullptr; + RN *neighbours = nullptr; bool _isBuild{false}; bool _isBuildNeighbours{false}; }; -} \ No newline at end of file +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/spatial/Region.h b/openpgl/spatial/Region.h index 5a84cae..54b364e 100644 --- a/openpgl/spatial/Region.h +++ b/openpgl/spatial/Region.h @@ -3,151 +3,151 @@ #pragma once -#include "../openpgl_common.h" #include "../data/SampleStatistics.h" +#include "../openpgl_common.h" #ifdef OPENPGL_RADIANCE_CACHES - #include "../directional/OutgoingRadianceHistogram.h" +#include "../directional/OutgoingRadianceHistogram.h" #endif #include "IRegion.h" namespace openpgl { - template - struct Region: public IRegion - { - TDistribution distribution; - BBox regionBounds; - TTrainingStatistics trainingStatistics; - SampleStatistics sampleStatistics; - size_t numZeroValueSamples {0}; - bool splitFlag {false}; +template +struct Region : public IRegion +{ + TDistribution distribution; + BBox regionBounds; + TTrainingStatistics trainingStatistics; + SampleStatistics sampleStatistics; + size_t numZeroValueSamples{0}; + bool splitFlag{false}; #ifdef OPENPGL_RADIANCE_CACHES - OutgoingRadianceHistogram outRadianceHist; + OutgoingRadianceHistogram outRadianceHist; #endif - //bool valid{true}; + // bool valid{true}; - inline const BBox &getRegionBounds() const - { - return regionBounds; - } + inline const BBox &getRegionBounds() const + { + return regionBounds; + } - inline const BBox &getSampleBounds() const - { - return sampleStatistics.sampleBounds; - } + inline const BBox &getSampleBounds() const + { + return sampleStatistics.sampleBounds; + } #ifdef OPENPGL_RADIANCE_CACHES - Vector3 getOutgoingRadiance(const Vector3 dir) const override - { - return outRadianceHist.getOugoingRadiance(dir); - } + Vector3 getOutgoingRadiance(const Vector3 dir) const override + { + return outRadianceHist.getOugoingRadiance(dir); + } #endif - /* - TDistribution getDistribution(Point3 samplePosition, const bool &useParallaxComp) const + /* + TDistribution getDistribution(Point3 samplePosition, const bool &useParallaxComp) const + { + TDistribution pDistribution = distribution; + if(useParallaxComp) { - TDistribution pDistribution = distribution; - if(useParallaxComp) - { - Point3 pivotPosition = pDistribution._pivotPosition; - pDistribution.performRelativeParallaxShift(pivotPosition - samplePosition); - } - return pDistribution; + Point3 pivotPosition = pDistribution._pivotPosition; + pDistribution.performRelativeParallaxShift(pivotPosition - samplePosition); } - */ + return pDistribution; + } + */ - const TDistribution* getDistribution(Point3 samplePosition) const - { - return &distribution; - } + const TDistribution *getDistribution(Point3 samplePosition) const + { + return &distribution; + } - /* - void getDistribution(TDistribution &pDistribution, Point3 samplePosition, const bool &useParallaxComp) const + /* + void getDistribution(TDistribution &pDistribution, Point3 samplePosition, const bool &useParallaxComp) const + { + pDistribution = distribution; + if(useParallaxComp) { - pDistribution = distribution; - if(useParallaxComp) - { - Point3 pivotPosition = pDistribution._pivotPosition; - pDistribution.performRelativeParallaxShift(pivotPosition - samplePosition); - } - //return pDistribution; + Point3 pivotPosition = pDistribution._pivotPosition; + pDistribution.performRelativeParallaxShift(pivotPosition - samplePosition); } - */ + //return pDistribution; + } + */ - void serialize(std::ostream& stream) const - { - stream.write(reinterpret_cast(&valid), sizeof(valid)); - distribution.serialize(stream); - stream.write(reinterpret_cast(®ionBounds), sizeof(regionBounds)); - trainingStatistics.serialize(stream); - sampleStatistics.serialize(stream); + void serialize(std::ostream &stream) const + { + stream.write(reinterpret_cast(&valid), sizeof(valid)); + distribution.serialize(stream); + stream.write(reinterpret_cast(®ionBounds), sizeof(regionBounds)); + trainingStatistics.serialize(stream); + sampleStatistics.serialize(stream); #ifdef OPENPGL_RADIANCE_CACHES - outRadianceHist.serialize(stream); + outRadianceHist.serialize(stream); #endif - stream.write(reinterpret_cast(&numZeroValueSamples), sizeof(numZeroValueSamples)); - stream.write(reinterpret_cast(&splitFlag), sizeof(splitFlag)); - } + stream.write(reinterpret_cast(&numZeroValueSamples), sizeof(numZeroValueSamples)); + stream.write(reinterpret_cast(&splitFlag), sizeof(splitFlag)); + } - void deserialize(std::istream& stream) - { - stream.read(reinterpret_cast(&valid), sizeof(valid)); - distribution.deserialize(stream); - stream.read(reinterpret_cast(®ionBounds), sizeof(regionBounds)); - trainingStatistics.deserialize(stream); - sampleStatistics.deserialize(stream); + void deserialize(std::istream &stream) + { + stream.read(reinterpret_cast(&valid), sizeof(valid)); + distribution.deserialize(stream); + stream.read(reinterpret_cast(®ionBounds), sizeof(regionBounds)); + trainingStatistics.deserialize(stream); + sampleStatistics.deserialize(stream); #ifdef OPENPGL_RADIANCE_CACHES - outRadianceHist.deserialize(stream); + outRadianceHist.deserialize(stream); #endif - stream.read(reinterpret_cast(&numZeroValueSamples), sizeof(numZeroValueSamples)); - stream.read(reinterpret_cast(&splitFlag), sizeof(splitFlag)); + stream.read(reinterpret_cast(&numZeroValueSamples), sizeof(numZeroValueSamples)); + stream.read(reinterpret_cast(&splitFlag), sizeof(splitFlag)); + } + + bool isValid() const + { + bool valid = true; + valid = valid && distribution.isValid(); + valid = valid && trainingStatistics.isValid(); + // valid = valid && sampleStatistics.isValid(); + return valid; + } + + std::string toString() const + { + std::stringstream ss; + ss.precision(5); + ss << "Region:" << std::endl; + ss << "\t regionBounds: " << regionBounds << std::endl; + ss << "\t distribution: " << distribution.toString() << std::endl; + ss << "\t trainingStatistics: " << trainingStatistics.toString() << std::endl; + ss << "\t sampleStatistics: " << sampleStatistics.toString() << std::endl; + ss << "\t splitFlag: " << splitFlag << std::endl; + ss << "\t valid: " << valid << std::endl; + return ss.str(); + } + + bool operator==(const Region &b) const + { + bool equal = true; + if (!sampleStatistics.operator==(b.sampleStatistics) || splitFlag != b.splitFlag) + { + equal = false; } - bool isValid() const + if (!distribution.operator==(b.distribution)) { - bool valid = true; - valid = valid && distribution.isValid(); - valid = valid && trainingStatistics.isValid(); -// valid = valid && sampleStatistics.isValid(); - return valid; + equal = false; } - std::string toString() const + if (!trainingStatistics.operator==(b.trainingStatistics)) { - std::stringstream ss; - ss.precision(5); - ss << "Region:" << std::endl; - ss << "\t regionBounds: " << regionBounds << std::endl; - ss << "\t distribution: " << distribution.toString() << std::endl; - ss << "\t trainingStatistics: " << trainingStatistics.toString() << std::endl; - ss << "\t sampleStatistics: " << sampleStatistics.toString() << std::endl; - ss << "\t splitFlag: " << splitFlag << std::endl; - ss << "\t valid: " << valid << std::endl; - return ss.str(); + equal = false; } - bool operator==(const Region& b) const { - bool equal = true; - if (!sampleStatistics.operator==(b.sampleStatistics) || splitFlag != b.splitFlag) - { - equal = false; - } - - if (!distribution.operator==(b.distribution)) - { - equal = false; - } - - if (!trainingStatistics.operator==(b.trainingStatistics)) - { - equal = false; - } - - if (!(regionBounds == b.regionBounds)) - { - equal = false; - } - - return equal; + if (!(regionBounds == b.regionBounds)) + { + equal = false; } - }; -} \ No newline at end of file + return equal; + } +}; +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/spatial/kdtree/KDTree.h b/openpgl/spatial/kdtree/KDTree.h index a203a1e..77a5021 100644 --- a/openpgl/spatial/kdtree/KDTree.h +++ b/openpgl/spatial/kdtree/KDTree.h @@ -3,15 +3,14 @@ #pragma once -#include "../../openpgl_common.h" - #include -#include "KDTreeStatistics.h" - #include -#include #include +#include + +#include "../../openpgl_common.h" +#include "KDTreeStatistics.h" #define USE_TREELETS @@ -20,14 +19,15 @@ namespace openpgl struct KDNode { - enum{ + enum + { ESPlitDimX = 0, ESPlitDimY = 1, ESPlitDimZ = 2, - ELeafNode = 3, + ELeafNode = 3, }; - float splitPosition {0.0f}; + float splitPosition{0.0f}; uint32_t splitDimAndNodeIdx{0}; ///////////////////////////// @@ -35,72 +35,77 @@ struct KDNode ///////////////////////////// bool isChild() const { - return ( splitDimAndNodeIdx >> 30) < ELeafNode; + return (splitDimAndNodeIdx >> 30) < ELeafNode; } - void setLeftChildIdx(const uint32_t &idx) { - OPENPGL_ASSERT(idx < (1U<<31)); - OPENPGL_ASSERT( (splitDimAndNodeIdx & (3U << 30)) != (3U<<30)); - OPENPGL_ASSERT( (splitDimAndNodeIdx >> 30) != 3); - OPENPGL_ASSERT( !isLeaf() ); + void setLeftChildIdx(const uint32_t &idx) + { + OPENPGL_ASSERT(idx < (1U << 31)); + OPENPGL_ASSERT((splitDimAndNodeIdx & (3U << 30)) != (3U << 30)); + OPENPGL_ASSERT((splitDimAndNodeIdx >> 30) != 3); + OPENPGL_ASSERT(!isLeaf()); - splitDimAndNodeIdx = ((splitDimAndNodeIdx >> 30) << 30)|idx; - OPENPGL_ASSERT( idx == getLeftChildIdx()); + splitDimAndNodeIdx = ((splitDimAndNodeIdx >> 30) << 30) | idx; + OPENPGL_ASSERT(idx == getLeftChildIdx()); } - uint32_t getLeftChildIdx() const { - OPENPGL_ASSERT( (splitDimAndNodeIdx & (3U << 30)) != (3U<<30)); - OPENPGL_ASSERT( (splitDimAndNodeIdx >> 30) != 3); - OPENPGL_ASSERT( !isLeaf() ); + uint32_t getLeftChildIdx() const + { + OPENPGL_ASSERT((splitDimAndNodeIdx & (3U << 30)) != (3U << 30)); + OPENPGL_ASSERT((splitDimAndNodeIdx >> 30) != 3); + OPENPGL_ASSERT(!isLeaf()); return (splitDimAndNodeIdx << 2) >> 2; - } + } ///////////////////////////// // Inner node functions ///////////////////////////// - void setToInnerNode( const uint8_t &_splitDim, const float &_splitPos, const uint32_t &_leftChildIdx) { + void setToInnerNode(const uint8_t &_splitDim, const float &_splitPos, const uint32_t &_leftChildIdx) + { splitPosition = _splitPos; splitDimAndNodeIdx = 0; - splitDimAndNodeIdx = (uint32_t(_splitDim)<<30); - splitDimAndNodeIdx = ((splitDimAndNodeIdx >> 30) << 30)|_leftChildIdx; + splitDimAndNodeIdx = (uint32_t(_splitDim) << 30); + splitDimAndNodeIdx = ((splitDimAndNodeIdx >> 30) << 30) | _leftChildIdx; OPENPGL_ASSERT(_splitDim == getSplitDim()); OPENPGL_ASSERT(_leftChildIdx == getLeftChildIdx()); } - ///////////////////////////// // Leaf node functions ///////////////////////////// - void setLeaf(){ - splitDimAndNodeIdx = (3U<<30); + void setLeaf() + { + splitDimAndNodeIdx = (3U << 30); OPENPGL_ASSERT(isLeaf()); } - bool isLeaf() const { + bool isLeaf() const + { return (splitDimAndNodeIdx >> 30) == 3; } - void setChildNodeIdx(const uint32_t &idx) { - OPENPGL_ASSERT(idx < (1U<<31)); - OPENPGL_ASSERT( (splitDimAndNodeIdx & (3U << 30)) != (3U<<30)); - OPENPGL_ASSERT( (splitDimAndNodeIdx >> 30) != 3); - OPENPGL_ASSERT( !isLeaf() ); + void setChildNodeIdx(const uint32_t &idx) + { + OPENPGL_ASSERT(idx < (1U << 31)); + OPENPGL_ASSERT((splitDimAndNodeIdx & (3U << 30)) != (3U << 30)); + OPENPGL_ASSERT((splitDimAndNodeIdx >> 30) != 3); + OPENPGL_ASSERT(!isLeaf()); - splitDimAndNodeIdx = ((splitDimAndNodeIdx >> 30) << 30)|idx; - OPENPGL_ASSERT( idx == getLeftChildIdx()); + splitDimAndNodeIdx = ((splitDimAndNodeIdx >> 30) << 30) | idx; + OPENPGL_ASSERT(idx == getLeftChildIdx()); } void setDataNodeIdx(const uint32_t &idx) { - OPENPGL_ASSERT(idx < (1U<<31)); // checks if the idx is in the right range + OPENPGL_ASSERT(idx < (1U << 31)); // checks if the idx is in the right range setLeaf(); - splitDimAndNodeIdx = ((splitDimAndNodeIdx >> 30) << 30)|idx; - OPENPGL_ASSERT( isLeaf()); - OPENPGL_ASSERT( getDataIdx() == idx); + splitDimAndNodeIdx = ((splitDimAndNodeIdx >> 30) << 30) | idx; + OPENPGL_ASSERT(isLeaf()); + OPENPGL_ASSERT(getDataIdx() == idx); } uint32_t getDataIdx() const @@ -109,7 +114,6 @@ struct KDNode return (splitDimAndNodeIdx << 2) >> 2; } - ///////////////////////////// // Split dimension functions ///////////////////////////// @@ -119,54 +123,58 @@ struct KDNode return (splitDimAndNodeIdx >> 30); } - void setSplitDim(const uint8_t &splitAxis) { - OPENPGL_ASSERT(splitAxis(&splitPosition), sizeof(float)); - stream.write(reinterpret_cast(&splitDimAndNodeIdx), sizeof(uint32_t)); + stream.write(reinterpret_cast(&splitPosition), sizeof(float)); + stream.write(reinterpret_cast(&splitDimAndNodeIdx), sizeof(uint32_t)); } - void deserialize(std::istream& stream) + void deserialize(std::istream &stream) { - stream.read(reinterpret_cast(&splitPosition), sizeof(float)); - stream.read(reinterpret_cast(&splitDimAndNodeIdx), sizeof(uint32_t)); + stream.read(reinterpret_cast(&splitPosition), sizeof(float)); + stream.read(reinterpret_cast(&splitDimAndNodeIdx), sizeof(uint32_t)); } - bool operator==(const KDNode& b) const { + bool operator==(const KDNode &b) const + { bool equal = true; - if (splitPosition != b.splitPosition || isLeaf() != b.isLeaf()) + if (splitPosition != b.splitPosition || isLeaf() != b.isLeaf()) { equal = false; } if (!isLeaf()) { - if(getSplitDim() != b.getSplitDim() || - getLeftChildIdx() != b.getLeftChildIdx()) + if (getSplitDim() != b.getSplitDim() || getLeftChildIdx() != b.getLeftChildIdx()) { equal = false; } - } else { - if (getDataIdx() != b.getDataIdx()) + } + else + { + if (getDataIdx() != b.getDataIdx()) { equal = false; } } return equal; } - }; struct KDTreeLet @@ -174,20 +182,19 @@ struct KDTreeLet KDNode nodes[8]; }; - - struct KDTree { KDTree() = default; - KDTree(const KDTree&) = delete; + KDTree(const KDTree &) = delete; ~KDTree() { - if(m_nodesPtr) + if (m_nodesPtr) delete[] m_nodesPtr; - if(m_treeLets){ + if (m_treeLets) + { delete[] m_treeLets; m_treeLets = nullptr; m_numTreeLets = 0; @@ -213,27 +220,26 @@ struct KDTree m_nodes[0].setDataNodeIdx(0); } - KDNode& getRoot() + KDNode &getRoot() { return getNode(0); } - KDNode& getNode( const size_t &idx ) + KDNode &getNode(const size_t &idx) { - //OPENPGL_ASSERT( m_isInit ); - OPENPGL_ASSERT( m_nodes.size() > idx ); + // OPENPGL_ASSERT( m_isInit ); + OPENPGL_ASSERT(m_nodes.size() > idx); return m_nodes[idx]; } - - const KDNode& getRoot() const + const KDNode &getRoot() const { return getNode(0); } - const KDNode& getNode( const size_t &idx ) const + const KDNode &getNode(const size_t &idx) const { - OPENPGL_ASSERT( m_nodes.size() > idx ); + OPENPGL_ASSERT(m_nodes.size() > idx); return m_nodes[idx]; } @@ -244,8 +250,8 @@ struct KDTree uint32_t addChildrenPair() { - auto firstChildItr = m_nodes.grow_by(2); - return std::distance(m_nodes.begin(), firstChildItr); + auto firstChildItr = m_nodes.grow_by(2); + return std::distance(m_nodes.begin(), firstChildItr); } const BBox &getBounds() const @@ -253,19 +259,22 @@ struct KDTree return m_bounds; } - void rearrangeNodeForCompare(const KDNode& node, int idx, std::vector& newNodes, std::vector< uint32_t > &dataStorageIndices) const { + void rearrangeNodeForCompare(const KDNode &node, int idx, std::vector &newNodes, std::vector &dataStorageIndices) const + { if (!node.isLeaf()) { uint32_t leftIdx = node.getLeftChildIdx(); KDNode nodeLeft = m_nodes[leftIdx]; - KDNode nodeRight = m_nodes[leftIdx+1]; + KDNode nodeRight = m_nodes[leftIdx + 1]; uint32_t newIdx = newNodes.size(); newNodes[idx].setLeftChildIdx(newIdx); newNodes.push_back(nodeLeft); newNodes.push_back(nodeRight); rearrangeNodeForCompare(nodeLeft, newIdx, newNodes, dataStorageIndices); - rearrangeNodeForCompare(nodeRight, newIdx+1, newNodes, dataStorageIndices); - } else { + rearrangeNodeForCompare(nodeRight, newIdx + 1, newNodes, dataStorageIndices); + } + else + { uint32_t dataIdx = node.getDataIdx(); uint32_t newDataIdx = dataStorageIndices.size(); dataStorageIndices.push_back(dataIdx); @@ -273,9 +282,10 @@ struct KDTree } } - void rearrangeNodesForCompare(std::vector &newNodes, std::vector< uint32_t > &dataStorageIndices) const + void rearrangeNodesForCompare(std::vector &newNodes, std::vector &dataStorageIndices) const { - if (m_nodes.size() > 0) { + if (m_nodes.size() > 0) + { KDNode root = m_nodes[0]; newNodes.push_back(root); rearrangeNodeForCompare(root, 0, newNodes, dataStorageIndices); @@ -284,7 +294,8 @@ struct KDTree void finalize() { - if(m_nodesPtr){ + if (m_nodesPtr) + { delete[] m_nodesPtr; m_nodesPtr = nullptr; } @@ -292,19 +303,20 @@ struct KDTree if (nNodes > 0) { m_nodesPtr = new KDNode[nNodes]; - for(int n = 0; n < nNodes; n++) + for (int n = 0; n < nNodes; n++) { m_nodesPtr[n] = m_nodes[n]; } #ifdef USE_TREELETS buildTreeLets(); #endif - } + } } void buildTreeLets() { - if(m_treeLets){ + if (m_treeLets) + { delete[] m_treeLets; m_treeLets = nullptr; m_numTreeLets = 0; @@ -316,62 +328,74 @@ struct KDTree m_numTreeLets = treeLets.size(); m_treeLets = new KDTreeLet[m_numTreeLets]; - for ( int i = 0; i < m_numTreeLets; i++){ + for (int i = 0; i < m_numTreeLets; i++) + { m_treeLets[i] = treeLets[i]; } } - uint32_t insertNode(const KDNode& node, uint32_t nodeIdx, uint32_t treeLetIdx, uint32_t treeDepth, std::vector& treeLets) { + uint32_t insertNode(const KDNode &node, uint32_t nodeIdx, uint32_t treeLetIdx, uint32_t treeDepth, std::vector &treeLets) + { uint32_t treeLetLevel = treeDepth % 3; uint32_t globalNodeId = (treeLetIdx * 8) + nodeIdx; treeLets[treeLetIdx].nodes[nodeIdx] = node; - if (!node.isLeaf()) { - if(treeLetLevel == 0) { + if (!node.isLeaf()) + { + if (treeLetLevel == 0) + { uint32_t childIdx = node.getLeftChildIdx(); - uint32_t newChildIdx = insertNode(m_nodesPtr[childIdx], 1, treeLetIdx, treeDepth+1,treeLets); - insertNode(m_nodesPtr[childIdx+1], 2, treeLetIdx, treeDepth+1,treeLets); + uint32_t newChildIdx = insertNode(m_nodesPtr[childIdx], 1, treeLetIdx, treeDepth + 1, treeLets); + insertNode(m_nodesPtr[childIdx + 1], 2, treeLetIdx, treeDepth + 1, treeLets); treeLets[treeLetIdx].nodes[nodeIdx].setLeftChildIdx(newChildIdx); OPENPGL_ASSERT(node.getSplitDim() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitDim()); OPENPGL_ASSERT(node.getSplitPivot() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitPivot()); OPENPGL_ASSERT(newChildIdx == treeLets[treeLetIdx].nodes[nodeIdx].getLeftChildIdx()); - } else if (treeLetLevel == 1) { - if(nodeIdx == 1) + } + else if (treeLetLevel == 1) + { + if (nodeIdx == 1) { uint32_t childIdx = node.getLeftChildIdx(); - uint32_t newChildIdx = insertNode(m_nodesPtr[childIdx], 3, treeLetIdx, treeDepth+1,treeLets); - insertNode(m_nodesPtr[childIdx+1], 4, treeLetIdx, treeDepth+1,treeLets); + uint32_t newChildIdx = insertNode(m_nodesPtr[childIdx], 3, treeLetIdx, treeDepth + 1, treeLets); + insertNode(m_nodesPtr[childIdx + 1], 4, treeLetIdx, treeDepth + 1, treeLets); treeLets[treeLetIdx].nodes[nodeIdx].setLeftChildIdx(newChildIdx); OPENPGL_ASSERT(node.getSplitDim() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitDim()); OPENPGL_ASSERT(node.getSplitPivot() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitPivot()); OPENPGL_ASSERT(newChildIdx == treeLets[treeLetIdx].nodes[nodeIdx].getLeftChildIdx()); - } else if (nodeIdx == 2) { + } + else if (nodeIdx == 2) + { uint32_t childIdx = node.getLeftChildIdx(); - uint32_t newChildIdx = insertNode(m_nodesPtr[childIdx], 5, treeLetIdx, treeDepth+1,treeLets); - insertNode(m_nodesPtr[childIdx+1], 6, treeLetIdx, treeDepth+1,treeLets); + uint32_t newChildIdx = insertNode(m_nodesPtr[childIdx], 5, treeLetIdx, treeDepth + 1, treeLets); + insertNode(m_nodesPtr[childIdx + 1], 6, treeLetIdx, treeDepth + 1, treeLets); treeLets[treeLetIdx].nodes[nodeIdx].setLeftChildIdx(newChildIdx); OPENPGL_ASSERT(node.getSplitDim() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitDim()); OPENPGL_ASSERT(node.getSplitPivot() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitPivot()); OPENPGL_ASSERT(newChildIdx == treeLets[treeLetIdx].nodes[nodeIdx].getLeftChildIdx()); - } else { + } + else + { OPENPGL_ASSERT(false); } - } else { - OPENPGL_ASSERT(node.getSplitDim() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitDim()); - uint32_t childIdx = node.getLeftChildIdx(); - treeLets.push_back(KDTreeLet()); - treeLets.push_back(KDTreeLet()); - OPENPGL_ASSERT(node.getSplitDim() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitDim()); - uint32_t leftTreeLetIdx = treeLets.size() - 2; - insertNode(m_nodesPtr[childIdx], 0, leftTreeLetIdx, treeDepth+1,treeLets); - OPENPGL_ASSERT(node.getSplitDim() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitDim()); - insertNode(m_nodesPtr[childIdx+1], 0, leftTreeLetIdx+1, treeDepth+1,treeLets); - OPENPGL_ASSERT(node.getSplitDim() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitDim()); - treeLets[treeLetIdx].nodes[nodeIdx].setLeftChildIdx(leftTreeLetIdx); - OPENPGL_ASSERT(node.getSplitDim() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitDim()); + } + else + { + OPENPGL_ASSERT(node.getSplitDim() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitDim()); + uint32_t childIdx = node.getLeftChildIdx(); + treeLets.push_back(KDTreeLet()); + treeLets.push_back(KDTreeLet()); + OPENPGL_ASSERT(node.getSplitDim() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitDim()); + uint32_t leftTreeLetIdx = treeLets.size() - 2; + insertNode(m_nodesPtr[childIdx], 0, leftTreeLetIdx, treeDepth + 1, treeLets); + OPENPGL_ASSERT(node.getSplitDim() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitDim()); + insertNode(m_nodesPtr[childIdx + 1], 0, leftTreeLetIdx + 1, treeDepth + 1, treeLets); + OPENPGL_ASSERT(node.getSplitDim() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitDim()); + treeLets[treeLetIdx].nodes[nodeIdx].setLeftChildIdx(leftTreeLetIdx); + OPENPGL_ASSERT(node.getSplitDim() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitDim()); - OPENPGL_ASSERT(node.getSplitDim() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitDim()); - OPENPGL_ASSERT(node.getSplitPivot() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitPivot()); - OPENPGL_ASSERT(leftTreeLetIdx == treeLets[treeLetIdx].nodes[nodeIdx].getLeftChildIdx()); + OPENPGL_ASSERT(node.getSplitDim() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitDim()); + OPENPGL_ASSERT(node.getSplitPivot() == treeLets[treeLetIdx].nodes[nodeIdx].getSplitPivot()); + OPENPGL_ASSERT(leftTreeLetIdx == treeLets[treeLetIdx].nodes[nodeIdx].getLeftChildIdx()); } } return globalNodeId; @@ -383,7 +407,7 @@ struct KDTree OPENPGL_ASSERT(embree::inside(m_bounds, pos)); uint32_t nodeIdx = 0; - while(!m_nodesPtr[nodeIdx].isLeaf()) + while (!m_nodesPtr[nodeIdx].isLeaf()) { uint8_t splitDim = m_nodesPtr[nodeIdx].getSplitDim(); float pivot = m_nodesPtr[nodeIdx].getSplitPivot(); @@ -404,19 +428,22 @@ struct KDTree uint32_t nodeIdx = 0; uint32_t depth = 0; KDTreeLet treeLet = m_treeLets[treeIdx]; - - while(!treeLet.nodes[nodeIdx].isLeaf()) + + while (!treeLet.nodes[nodeIdx].isLeaf()) { uint8_t splitDim = treeLet.nodes[nodeIdx].getSplitDim(); uint32_t childIdx = treeLet.nodes[nodeIdx].getLeftChildIdx(); float pivot = treeLet.nodes[nodeIdx].getSplitPivot(); - - if(depth % 3 == 2){ + + if (depth % 3 == 2) + { nodeIdx = 0; treeIdx = childIdx; treeIdx += pos[splitDim] >= pivot ? 1 : 0; treeLet = m_treeLets[treeIdx]; - } else { + } + else + { nodeIdx = childIdx - (treeIdx * 8); nodeIdx += pos[splitDim] >= pivot ? 1 : 0; } @@ -425,24 +452,24 @@ struct KDTree return treeLet.nodes[nodeIdx].getDataIdx(); } #endif - uint32_t getMaxNodeDepth(const KDNode& node) const + uint32_t getMaxNodeDepth(const KDNode &node) const { - if(node.isLeaf()) + if (node.isLeaf()) { return 1; - } - else + } + else { const uint32_t leftNodeId = node.getLeftChildIdx(); const uint32_t leftMaxNodeDepth = getMaxNodeDepth(m_nodes[leftNodeId]); - const uint32_t rightMaxNodeDepth = getMaxNodeDepth(m_nodes[leftNodeId+1]); + const uint32_t rightMaxNodeDepth = getMaxNodeDepth(m_nodes[leftNodeId + 1]); return 1 + std::max(leftMaxNodeDepth, rightMaxNodeDepth); } - } + } uint32_t getMaxTreeDepth() const { - if(m_nodes.size()>0) + if (m_nodes.size() > 0) { return getMaxNodeDepth(m_nodes[0]); } @@ -454,8 +481,8 @@ struct KDTree std::stringstream ss; ss.precision(5); ss << "KDTree::" << std::endl; - ss << " isInit: " << m_isInit << std::endl; - ss << " bounds: " << m_bounds<< std::endl; + ss << " isInit: " << m_isInit << std::endl; + ss << " bounds: " << m_bounds << std::endl; ss << " maxDepth: " << getMaxTreeDepth() << std::endl; ss << " numNodes: " << m_nodes.size() << std::endl; return ss.str(); @@ -469,25 +496,24 @@ struct KDTree BBox rootBBox = m_bounds; const KDNode &root = getRoot(); uint32_t vertexOffset = 0; - exportKDNodeToObj(objFile, root, rootBBox,vertexOffset); + exportKDNodeToObj(objFile, root, rootBBox, vertexOffset); objFile.close(); } - void exportKDNodeToObj(std::ofstream &objFile, const KDNode &node, BBox bbox, uint32_t &vertexIDOffset) const { - if(!node.isLeaf()) + if (!node.isLeaf()) { const uint32_t leftNodeId = node.getLeftChildIdx(); const uint8_t splitDim = node.getSplitDim(); - const float splitPosition =node.getSplitPivot(); + const float splitPosition = node.getSplitPivot(); BBox bboxLeft = bbox; bboxLeft.upper[splitDim] = splitPosition; BBox bboxRight = bbox; bboxRight.lower[splitDim] = splitPosition; const KDNode &nodeLeft = m_nodes[leftNodeId]; - const KDNode &nodeRight = m_nodes[leftNodeId+1]; + const KDNode &nodeRight = m_nodes[leftNodeId + 1]; exportKDNodeToObj(objFile, nodeLeft, bboxLeft, vertexIDOffset); exportKDNodeToObj(objFile, nodeRight, bboxRight, vertexIDOffset); @@ -495,7 +521,7 @@ struct KDTree else { const uint32_t leafNodeId = node.getDataIdx(); - objFile << "# KDLeafNode"<< leafNodeId << std::endl; + objFile << "# KDLeafNode" << leafNodeId << std::endl; objFile << "v " << bbox.lower[0] << "\t" << bbox.lower[1] << "\t" << bbox.lower[2] << std::endl; objFile << "v " << bbox.lower[0] << "\t" << bbox.upper[1] << "\t" << bbox.lower[2] << std::endl; @@ -507,24 +533,23 @@ struct KDTree objFile << "v " << bbox.upper[0] << "\t" << bbox.upper[1] << "\t" << bbox.upper[2] << std::endl; objFile << "v " << bbox.upper[0] << "\t" << bbox.lower[1] << "\t" << bbox.upper[2] << std::endl; + objFile << "f " << vertexIDOffset + 1 + 0 << "\t" << vertexIDOffset + 1 + 1 << "\t" << vertexIDOffset + 1 + 2 << "\t" << vertexIDOffset + 1 + 3 << std::endl; + objFile << "f " << vertexIDOffset + 1 + 7 << "\t" << vertexIDOffset + 1 + 6 << "\t" << vertexIDOffset + 1 + 5 << "\t" << vertexIDOffset + 1 + 4 << std::endl; - objFile << "f " << vertexIDOffset+1 + 0 << "\t" << vertexIDOffset+1 + 1 << "\t" << vertexIDOffset+1 + 2 << "\t" << vertexIDOffset+1 + 3 << std::endl; - objFile << "f " << vertexIDOffset+1 + 7 << "\t" << vertexIDOffset+1 + 6 << "\t" << vertexIDOffset+1 + 5 << "\t" << vertexIDOffset+1 + 4 << std::endl; + objFile << "f " << vertexIDOffset + 1 + 0 << "\t" << vertexIDOffset + 1 + 3 << "\t" << vertexIDOffset + 1 + 7 << "\t" << vertexIDOffset + 1 + 4 << std::endl; + objFile << "f " << vertexIDOffset + 1 + 5 << "\t" << vertexIDOffset + 1 + 6 << "\t" << vertexIDOffset + 1 + 2 << "\t" << vertexIDOffset + 1 + 1 << std::endl; - - objFile << "f " << vertexIDOffset+1 + 0 << "\t" << vertexIDOffset+1 + 3 << "\t" << vertexIDOffset+1 + 7 << "\t" << vertexIDOffset+1 + 4 << std::endl; - objFile << "f " << vertexIDOffset+1 + 5 << "\t" << vertexIDOffset+1 + 6 << "\t" << vertexIDOffset+1 + 2 << "\t" << vertexIDOffset+1 + 1 << std::endl; - - objFile << "f " << vertexIDOffset+1 + 5 << "\t" << vertexIDOffset+1 + 1 << "\t" << vertexIDOffset+1 + 0 << "\t" << vertexIDOffset+1 + 4 << std::endl; - objFile << "f " << vertexIDOffset+1 + 7 << "\t" << vertexIDOffset+1 + 3 << "\t" << vertexIDOffset+1 + 2 << "\t" << vertexIDOffset+1 + 6 << std::endl; + objFile << "f " << vertexIDOffset + 1 + 5 << "\t" << vertexIDOffset + 1 + 1 << "\t" << vertexIDOffset + 1 + 0 << "\t" << vertexIDOffset + 1 + 4 << std::endl; + objFile << "f " << vertexIDOffset + 1 + 7 << "\t" << vertexIDOffset + 1 + 3 << "\t" << vertexIDOffset + 1 + 2 << "\t" << vertexIDOffset + 1 + 6 << std::endl; vertexIDOffset += 8; - //std::cout << "BBox: lower = [" << bbox.lower[0] << ",\t"<< bbox.lower[1] << ",\t"<< bbox.lower[2] << "] \t upper = ["<< bbox.upper[0] << ",\t"<< bbox.upper[1] << ",\t"<< bbox.upper[2] << std::endl; + // std::cout << "BBox: lower = [" << bbox.lower[0] << ",\t"<< bbox.lower[1] << ",\t"<< bbox.lower[2] << "] \t upper = ["<< bbox.upper[0] << ",\t"<< bbox.upper[1] << + // ",\t"<< bbox.upper[2] << std::endl; } } - template - void exportSampleBoundsToObj(std::string objFileName, const tbb::concurrent_vector< std::pair > &dataStorage) const + template + void exportSampleBoundsToObj(std::string objFileName, const tbb::concurrent_vector > &dataStorage) const { std::ofstream objFile; objFile.open(objFileName.c_str()); @@ -532,26 +557,27 @@ struct KDTree BBox rootBBox = m_bounds; const KDNode &root = getRoot(); uint32_t vertexOffset = 0; - exportSampleBoundToObj(objFile, root, rootBBox,vertexOffset, dataStorage); + exportSampleBoundToObj(objFile, root, rootBBox, vertexOffset, dataStorage); objFile.close(); } - template + template - void exportSampleBoundToObj(std::ofstream &objFile, const KDNode &node, BBox bbox, uint32_t &vertexIDOffset, const tbb::concurrent_vector< std::pair > &dataStorage) const + void exportSampleBoundToObj(std::ofstream &objFile, const KDNode &node, BBox bbox, uint32_t &vertexIDOffset, + const tbb::concurrent_vector > &dataStorage) const { - if(!node.isLeaf()) + if (!node.isLeaf()) { const uint32_t leftNodeId = node.getLeftChildIdx(); const uint8_t splitDim = node.getSplitDim(); - const float splitPosition =node.getSplitPivot(); + const float splitPosition = node.getSplitPivot(); BBox bboxLeft = bbox; bboxLeft.upper[splitDim] = splitPosition; BBox bboxRight = bbox; bboxRight.lower[splitDim] = splitPosition; const KDNode &nodeLeft = m_nodes[leftNodeId]; - const KDNode &nodeRight = m_nodes[leftNodeId+1]; + const KDNode &nodeRight = m_nodes[leftNodeId + 1]; exportSampleBoundToObj(objFile, nodeLeft, bboxLeft, vertexIDOffset, dataStorage); exportSampleBoundToObj(objFile, nodeRight, bboxRight, vertexIDOffset, dataStorage); @@ -562,7 +588,7 @@ struct KDTree const std::pair ®ionAndRange = dataStorage[leafNodeId]; BBox sampleBound = regionAndRange.first.sampleStatistics.sampleBounds; - objFile << "# SampleBound"<< leafNodeId << std::endl; + objFile << "# SampleBound" << leafNodeId << std::endl; objFile << "v " << sampleBound.lower[0] << "\t" << sampleBound.lower[1] << "\t" << sampleBound.lower[2] << std::endl; objFile << "v " << sampleBound.lower[0] << "\t" << sampleBound.upper[1] << "\t" << sampleBound.lower[2] << std::endl; @@ -574,39 +600,37 @@ struct KDTree objFile << "v " << sampleBound.upper[0] << "\t" << sampleBound.upper[1] << "\t" << sampleBound.upper[2] << std::endl; objFile << "v " << sampleBound.upper[0] << "\t" << sampleBound.lower[1] << "\t" << sampleBound.upper[2] << std::endl; + objFile << "f " << vertexIDOffset + 1 + 0 << "\t" << vertexIDOffset + 1 + 1 << "\t" << vertexIDOffset + 1 + 2 << "\t" << vertexIDOffset + 1 + 3 << std::endl; + objFile << "f " << vertexIDOffset + 1 + 7 << "\t" << vertexIDOffset + 1 + 6 << "\t" << vertexIDOffset + 1 + 5 << "\t" << vertexIDOffset + 1 + 4 << std::endl; - objFile << "f " << vertexIDOffset+1 + 0 << "\t" << vertexIDOffset+1 + 1 << "\t" << vertexIDOffset+1 + 2 << "\t" << vertexIDOffset+1 + 3 << std::endl; - objFile << "f " << vertexIDOffset+1 + 7 << "\t" << vertexIDOffset+1 + 6 << "\t" << vertexIDOffset+1 + 5 << "\t" << vertexIDOffset+1 + 4 << std::endl; + objFile << "f " << vertexIDOffset + 1 + 0 << "\t" << vertexIDOffset + 1 + 3 << "\t" << vertexIDOffset + 1 + 7 << "\t" << vertexIDOffset + 1 + 4 << std::endl; + objFile << "f " << vertexIDOffset + 1 + 5 << "\t" << vertexIDOffset + 1 + 6 << "\t" << vertexIDOffset + 1 + 2 << "\t" << vertexIDOffset + 1 + 1 << std::endl; - - objFile << "f " << vertexIDOffset+1 + 0 << "\t" << vertexIDOffset+1 + 3 << "\t" << vertexIDOffset+1 + 7 << "\t" << vertexIDOffset+1 + 4 << std::endl; - objFile << "f " << vertexIDOffset+1 + 5 << "\t" << vertexIDOffset+1 + 6 << "\t" << vertexIDOffset+1 + 2 << "\t" << vertexIDOffset+1 + 1 << std::endl; - - objFile << "f " << vertexIDOffset+1 + 5 << "\t" << vertexIDOffset+1 + 1 << "\t" << vertexIDOffset+1 + 0 << "\t" << vertexIDOffset+1 + 4 << std::endl; - objFile << "f " << vertexIDOffset+1 + 7 << "\t" << vertexIDOffset+1 + 3 << "\t" << vertexIDOffset+1 + 2 << "\t" << vertexIDOffset+1 + 6 << std::endl; + objFile << "f " << vertexIDOffset + 1 + 5 << "\t" << vertexIDOffset + 1 + 1 << "\t" << vertexIDOffset + 1 + 0 << "\t" << vertexIDOffset + 1 + 4 << std::endl; + objFile << "f " << vertexIDOffset + 1 + 7 << "\t" << vertexIDOffset + 1 + 3 << "\t" << vertexIDOffset + 1 + 2 << "\t" << vertexIDOffset + 1 + 6 << std::endl; vertexIDOffset += 8; } } - void serialize(std::ostream& stream)const + void serialize(std::ostream &stream) const { - stream.write(reinterpret_cast(&m_isInit), sizeof(bool)); - stream.write(reinterpret_cast(&m_bounds), sizeof(BBox)); + stream.write(reinterpret_cast(&m_isInit), sizeof(bool)); + stream.write(reinterpret_cast(&m_bounds), sizeof(BBox)); size_t num_nodes = m_nodes.size(); - stream.write(reinterpret_cast(&num_nodes), sizeof(size_t)); + stream.write(reinterpret_cast(&num_nodes), sizeof(size_t)); for (size_t n = 0; n < num_nodes; n++) { m_nodes[n].serialize(stream); } } - void deserialize(std::istream& stream) + void deserialize(std::istream &stream) { - stream.read(reinterpret_cast(&m_isInit), sizeof(bool)); - stream.read(reinterpret_cast(&m_bounds), sizeof(BBox)); + stream.read(reinterpret_cast(&m_isInit), sizeof(bool)); + stream.read(reinterpret_cast(&m_bounds), sizeof(BBox)); size_t num_nodes = 0; - stream.read(reinterpret_cast(&num_nodes), sizeof(size_t)); + stream.read(reinterpret_cast(&num_nodes), sizeof(size_t)); m_nodes.reserve(num_nodes); m_nodesPtr = new KDNode[num_nodes]; for (size_t n = 0; n < num_nodes; n++) @@ -617,51 +641,54 @@ struct KDTree m_nodesPtr[n] = node; } #ifdef USE_TREELETS - if(num_nodes > 0) + if (num_nodes > 0) buildTreeLets(); #endif - } - bool operator==(const KDTree& b) const { + bool operator==(const KDTree &b) const + { bool equal = true; - if (m_isInit != b.m_isInit || m_bounds.lower.x != b.m_bounds.lower.x || - m_bounds.lower.y != b.m_bounds.lower.y || m_bounds.lower.z != b.m_bounds.lower.z || - m_bounds.upper.x != b.m_bounds.upper.x || m_bounds.upper.y != b.m_bounds.upper.y || - m_bounds.upper.z != b.m_bounds.upper.z || - m_numTreeLets != b.m_numTreeLets) + if (m_isInit != b.m_isInit || m_bounds.lower.x != b.m_bounds.lower.x || m_bounds.lower.y != b.m_bounds.lower.y || m_bounds.lower.z != b.m_bounds.lower.z || + m_bounds.upper.x != b.m_bounds.upper.x || m_bounds.upper.y != b.m_bounds.upper.y || m_bounds.upper.z != b.m_bounds.upper.z || m_numTreeLets != b.m_numTreeLets) { equal = false; } if (m_nodes.size() == b.m_nodes.size()) { - for (int n = 0; n < m_nodes.size(); n++) { - if (!m_nodes[n].operator==(b.m_nodes[n])) { + for (int n = 0; n < m_nodes.size(); n++) + { + if (!m_nodes[n].operator==(b.m_nodes[n])) + { equal = false; - } } - } else { + } + else + { equal = false; } return equal; } - int calculateMaxDepth(const KDNode& node) const + int calculateMaxDepth(const KDNode &node) const { - if(node.isLeaf()){ + if (node.isLeaf()) + { return 1; - } else { + } + else + { int childIdxLeft = node.getLeftChildIdx(); int depthLeft = calculateMaxDepth(m_nodes[childIdxLeft]); - int depthRight = calculateMaxDepth(m_nodes[childIdxLeft+1]); + int depthRight = calculateMaxDepth(m_nodes[childIdxLeft + 1]); return 1 + std::max(depthLeft, depthRight); } } - KDTreeStatistics getStatistics() const + KDTreeStatistics getStatistics() const { KDTreeStatistics treeStats; treeStats.maxDepth = calculateMaxDepth(m_nodes[0]); @@ -673,9 +700,8 @@ struct KDTree return treeStats; } - -public: - bool m_isInit { false }; + public: + bool m_isInit{false}; // bounds of the spatial region covered by the KDTree BBox m_bounds; @@ -684,10 +710,10 @@ struct KDTree tbb::concurrent_vector m_nodes; // node storage used during querying - KDNode* m_nodesPtr {nullptr}; + KDNode *m_nodesPtr{nullptr}; - KDTreeLet* m_treeLets {nullptr}; - int m_numTreeLets {0}; + KDTreeLet *m_treeLets{nullptr}; + int m_numTreeLets{0}; }; -} \ No newline at end of file +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/spatial/kdtree/KDTreeBuilder.h b/openpgl/spatial/kdtree/KDTreeBuilder.h index 20ea4c0..99506cb 100644 --- a/openpgl/spatial/kdtree/KDTreeBuilder.h +++ b/openpgl/spatial/kdtree/KDTreeBuilder.h @@ -3,11 +3,11 @@ #pragma once -#include "../../openpgl_common.h" -#include "KDTree.h" -#include "../../data/SampleStatistics.h" #include "../../data/Range.h" +#include "../../data/SampleStatistics.h" #include "../../include/openpgl/types.h" +#include "../../openpgl_common.h" +#include "KDTree.h" #ifdef USE_EMBREE_PARALLEL #define TASKING_TBB @@ -20,17 +20,17 @@ #endif */ #include - #include -#include #include +#include + #include #include namespace openpgl { -template +template struct KDTreePartitionBuilder { const static PGL_SPATIAL_STRUCTURE_TYPE SPATIAL_STRUCTURE_TYPE = PGL_SPATIAL_STRUCTURE_KDTREE; @@ -44,18 +44,18 @@ struct KDTreePartitionBuilder struct Settings { - size_t minSamples {100}; - size_t maxSamples {PGL_TREE_MAX_SAMPLE_PER_LEAF}; - size_t maxDepth {32}; + size_t minSamples{100}; + size_t maxSamples{PGL_TREE_MAX_SAMPLE_PER_LEAF}; + size_t maxDepth{32}; - void serialize(std::ostream& stream) const; - void deserialize(std::istream& stream); + void serialize(std::ostream &stream) const; + void deserialize(std::istream &stream); std::string toString() const; - bool operator==(const Settings& b) const { + bool operator==(const Settings &b) const + { bool equal = true; - if(minSamples != b.minSamples || maxSamples != b.maxSamples || - maxDepth != b.maxDepth) + if (minSamples != b.minSamples || maxSamples != b.maxSamples || maxDepth != b.maxDepth) { equal = false; } @@ -63,9 +63,8 @@ struct KDTreePartitionBuilder } }; - void build(KDTree &kdTree, const BBox &bounds, TSamplesContainer &samples, tbb::concurrent_vector< std::pair > &dataStorage, const Settings &buildSettings) const + void build(KDTree &kdTree, const BBox &bounds, TSamplesContainer &samples, tbb::concurrent_vector > &dataStorage, const Settings &buildSettings) const { - kdTree.init(bounds, 4096); dataStorage.resize(1); dataStorage[0].first.regionBounds = bounds; @@ -73,11 +72,11 @@ struct KDTreePartitionBuilder updateTree(kdTree, samples, dataStorage, buildSettings); } - void updateTree(KDTree &kdTree, TSamplesContainer &samples, tbb::concurrent_vector< std::pair > &dataStorage, const Settings &buildSettings) const + void updateTree(KDTree &kdTree, TSamplesContainer &samples, tbb::concurrent_vector > &dataStorage, const Settings &buildSettings) const { - int numEstLeafs = dataStorage.size() + (samples.size()*2)/buildSettings.maxSamples+32; - kdTree.m_nodes.reserve(4*numEstLeafs); - dataStorage.reserve(2*numEstLeafs); + int numEstLeafs = dataStorage.size() + (samples.size() * 2) / buildSettings.maxSamples + 32; + kdTree.m_nodes.reserve(4 * numEstLeafs); + dataStorage.reserve(2 * numEstLeafs); KDNode &root = kdTree.getRoot(); SampleStatistics sampleStats; @@ -89,23 +88,29 @@ struct KDTreePartitionBuilder sampleRange.m_begin = 0; sampleRange.m_end = samples.size(); - size_t depth =1; + size_t depth = 1; if (root.isLeaf()) { #ifdef USE_EMBREE_PARALLEL - IntegerSampleStatistics iSampleStats = embree::parallel_reduce(size_t(0), samples.size(), IntegerSampleStatistics(bounds), [&] (const embree::range& r) -> IntegerSampleStatistics { - IntegerSampleStatistics stats(bounds); - for (size_t i=r.begin(); i &r) -> IntegerSampleStatistics { + IntegerSampleStatistics stats(bounds); + for (size_t i = r.begin(); i < r.end(); i++) + { + const PGLSampleData sample = samples[i]; + const Point3 samplePosition(sample.position.x, sample.position.y, sample.position.z); + stats.addSample(samplePosition); + } + return stats; + }, + [](const IntegerSampleStatistics &a, const IntegerSampleStatistics &b) { + return IntegerSampleStatistics::merge(a, b); + }); #else IntegerSampleStatistics iSampleStats(bounds); - for (const auto& sample : samples) + for (const auto &sample : samples) { const Point3 samplePosition(sample.position.x, sample.position.y, sample.position.z); iSampleStats.addSample(samplePosition); @@ -117,8 +122,7 @@ struct KDTreePartitionBuilder kdTree.finalize(); } - -void insertTree(KDTree &kdTree, TZeroValueSamplesContainer &samples, tbb::concurrent_vector< std::pair > &dataStorage) const + void insertTree(KDTree &kdTree, TZeroValueSamplesContainer &samples, tbb::concurrent_vector > &dataStorage) const { KDNode &root = kdTree.getRoot(); @@ -126,40 +130,37 @@ void insertTree(KDTree &kdTree, TZeroValueSamplesContainer &samples, tbb::concur sampleRange.m_begin = 0; sampleRange.m_end = samples.size(); - size_t depth =1; + size_t depth = 1; insertTreeNode(&kdTree, root, depth, samples, sampleRange, &dataStorage); } std::string toString() const; -private: - template - inline typename TContainer::iterator pivotSplitSamples(typename TContainer::iterator begin, typename TContainer::iterator end, - uint8_t splitDimension, float pivot) const + private: + template + inline typename TContainer::iterator pivotSplitSamples(typename TContainer::iterator begin, typename TContainer::iterator end, uint8_t splitDimension, float pivot) const { - std::function pivotSplitPredicate - = [splitDimension, pivot](typename TContainer::value_type sample) -> bool - { + std::function pivotSplitPredicate = [splitDimension, pivot](typename TContainer::value_type sample) -> bool { const Vector3 samplePosition(sample.position.x, sample.position.y, sample.position.z); return samplePosition[splitDimension] < pivot; - }; return std::partition(begin, end, pivotSplitPredicate); } - inline typename TSamplesContainer::iterator pivotSplitSamplesWithStats(typename TSamplesContainer::iterator begin, typename TSamplesContainer::iterator end, - uint8_t splitDimension, float pivot, SampleStatistics &statsLeft, SampleStatistics &statsRight) const + uint8_t splitDimension, float pivot, SampleStatistics &statsLeft, SampleStatistics &statsRight) const { - std::function pivotSplitPredicate - = [splitDimension, pivot, &statsLeft, &statsRight](typename TSamplesContainer::value_type sample) -> bool - { + std::function pivotSplitPredicate = [splitDimension, pivot, &statsLeft, + &statsRight](typename TSamplesContainer::value_type sample) -> bool { const Vector3 samplePosition(sample.position.x, sample.position.y, sample.position.z); bool left = samplePosition[splitDimension] < pivot; - if(left){ + if (left) + { statsLeft.addSample(samplePosition); - }else{ + } + else + { statsRight.addSample(samplePosition); } return left; @@ -168,61 +169,87 @@ void insertTree(KDTree &kdTree, TZeroValueSamplesContainer &samples, tbb::concur } #ifdef USE_EMBREE_PARALLEL - template - inline size_t pivotSplitSamples2(DataType* samples, const size_t begin, const size_t end, - uint8_t splitDimension, float pivot) const + template + inline size_t pivotSplitSamples2(DataType *samples, const size_t begin, const size_t end, uint8_t splitDimension, float pivot) const { - auto isLeft = [&] (const DataType &sample) { return Vector3(sample.position.x, sample.position.y, sample.position.z)[splitDimension] < pivot; }; + auto isLeft = [&](const DataType &sample) { + return Vector3(sample.position.x, sample.position.y, sample.position.z)[splitDimension] < pivot; + }; size_t center = 0; - bool parallel = (end-begin) < PARALLEL_THRESHOLD ? false : true; - if (!parallel) { + bool parallel = (end - begin) < PARALLEL_THRESHOLD ? false : true; + if (!parallel) + { center = embree::serial_partitioning(samples, begin, end, isLeft); - } else { + } + else + { center = embree::parallel_partitioning(samples, begin, end, isLeft, PARALLEL_PARTITION_BLOCK_SIZE); } return center; } - inline size_t pivotSplitSamplesWithStats2(PGLSampleData* samples, const size_t begin, const size_t end, - uint8_t splitDimension, float pivot, SampleStatistics &statsLeft, SampleStatistics &statsRight) const + inline size_t pivotSplitSamplesWithStats2(PGLSampleData *samples, const size_t begin, const size_t end, uint8_t splitDimension, float pivot, SampleStatistics &statsLeft, + SampleStatistics &statsRight) const { - auto isLeft = [&] (const PGLSampleData &sample) { const Vector3 v(sample.position.x, sample.position.y, sample.position.z); return v[splitDimension] < pivot; }; + auto isLeft = [&](const PGLSampleData &sample) { + const Vector3 v(sample.position.x, sample.position.y, sample.position.z); + return v[splitDimension] < pivot; + }; size_t center = 0; - bool parallel = (end-begin) < PARALLEL_THRESHOLD ? false : true; - if (!parallel) { - center = embree::serial_partitioning(samples, begin, end, statsLeft, statsRight, isLeft, - [] (SampleStatistics& sstats, const PGLSampleData& sample) { sstats.addSample(Vector3(sample.position.x, sample.position.y, sample.position.z)); }); - } else { - center = embree::parallel_partitioning(samples, begin, end, SampleStatistics(), - statsLeft, statsRight, isLeft, - [] (SampleStatistics& sstats, const PGLSampleData& sample) { sstats.addSample(Vector3(sample.position.x, sample.position.y, sample.position.z)); }, - [] (SampleStatistics& sstats0,const SampleStatistics& sstats1) { sstats0.merge(sstats1); }, - PARALLEL_PARTITION_BLOCK_SIZE); + bool parallel = (end - begin) < PARALLEL_THRESHOLD ? false : true; + if (!parallel) + { + center = embree::serial_partitioning(samples, begin, end, statsLeft, statsRight, isLeft, [](SampleStatistics &sstats, const PGLSampleData &sample) { + sstats.addSample(Vector3(sample.position.x, sample.position.y, sample.position.z)); + }); + } + else + { + center = embree::parallel_partitioning( + samples, begin, end, SampleStatistics(), statsLeft, statsRight, isLeft, + [](SampleStatistics &sstats, const PGLSampleData &sample) { + sstats.addSample(Vector3(sample.position.x, sample.position.y, sample.position.z)); + }, + [](SampleStatistics &sstats0, const SampleStatistics &sstats1) { + sstats0.merge(sstats1); + }, + PARALLEL_PARTITION_BLOCK_SIZE); } return center; } - inline size_t pivotSplitSamplesWithStats3(const BBox& bounds, PGLSampleData* samples, const size_t begin, const size_t end, - uint8_t splitDimension, float pivot, SampleStatistics &statsLeft, SampleStatistics &statsRight, bool parallel = true) const + inline size_t pivotSplitSamplesWithStats3(const BBox &bounds, PGLSampleData *samples, const size_t begin, const size_t end, uint8_t splitDimension, float pivot, + SampleStatistics &statsLeft, SampleStatistics &statsRight, bool parallel = true) const { - auto isLeft = [&] (const PGLSampleData &sample) { const Vector3 v(sample.position.x, sample.position.y, sample.position.z); return v[splitDimension] < pivot; }; + auto isLeft = [&](const PGLSampleData &sample) { + const Vector3 v(sample.position.x, sample.position.y, sample.position.z); + return v[splitDimension] < pivot; + }; size_t center = 0; - bool runParallel = (end-begin) < PARALLEL_THRESHOLD || parallel == false ? false : true; - if (!runParallel) { + bool runParallel = (end - begin) < PARALLEL_THRESHOLD || parallel == false ? false : true; + if (!runParallel) + { IntegerSampleStatistics iStatsLeft(bounds); IntegerSampleStatistics iStatsRight(bounds); - center = embree::serial_partitioning(samples, begin, end, iStatsLeft, iStatsRight, isLeft, - [] (IntegerSampleStatistics& sstats, const PGLSampleData& sample) { sstats.addSample(Vector3(sample.position.x, sample.position.y, sample.position.z)); }); + center = embree::serial_partitioning(samples, begin, end, iStatsLeft, iStatsRight, isLeft, [](IntegerSampleStatistics &sstats, const PGLSampleData &sample) { + sstats.addSample(Vector3(sample.position.x, sample.position.y, sample.position.z)); + }); statsLeft = iStatsLeft.getSampleStatistics(); statsRight = iStatsRight.getSampleStatistics(); - } else { + } + else + { IntegerSampleStatistics iStatsLeft(bounds); IntegerSampleStatistics iStatsRight(bounds); - center = embree::parallel_partitioning(samples, begin, end, IntegerSampleStatistics(bounds), - iStatsLeft, iStatsRight, isLeft, - [] (IntegerSampleStatistics& sstats, const PGLSampleData& sample) { sstats.addSample(Vector3(sample.position.x, sample.position.y, sample.position.z)); }, - [] (IntegerSampleStatistics& sstats0,const IntegerSampleStatistics& sstats1) { sstats0.merge(sstats1); }, - PARALLEL_PARTITION_BLOCK_SIZE); + center = embree::parallel_partitioning( + samples, begin, end, IntegerSampleStatistics(bounds), iStatsLeft, iStatsRight, isLeft, + [](IntegerSampleStatistics &sstats, const PGLSampleData &sample) { + sstats.addSample(Vector3(sample.position.x, sample.position.y, sample.position.z)); + }, + [](IntegerSampleStatistics &sstats0, const IntegerSampleStatistics &sstats1) { + sstats0.merge(sstats1); + }, + PARALLEL_PARTITION_BLOCK_SIZE); statsLeft = iStatsLeft.getSampleStatistics(); statsRight = iStatsRight.getSampleStatistics(); } @@ -235,8 +262,7 @@ void insertTree(KDTree &kdTree, TZeroValueSamplesContainer &samples, tbb::concur const Vector3 sampleVariance = sampleStats.getVariance(); const Point3 sampleMean = sampleStats.getMean(); - auto maxDimension = [](const Vector3& v) -> uint8_t - { + auto maxDimension = [](const Vector3 &v) -> uint8_t { return v[v[1] > v[0]] > v[2] ? v[1] > v[0] : 2; }; @@ -244,10 +270,10 @@ void insertTree(KDTree &kdTree, TZeroValueSamplesContainer &samples, tbb::concur splitPos = sampleMean[splitDim]; } - - void updateTreeNode(KDTree *kdTree, KDNode &node, size_t depth, const BBox bounds, TSamplesContainer &samples, const Range sampleRange, const SampleStatistics& sampleStats, tbb::concurrent_vector< std::pair > *dataStorage, const Settings &buildSettings, bool parallel = true) const + void updateTreeNode(KDTree *kdTree, KDNode &node, size_t depth, const BBox bounds, TSamplesContainer &samples, const Range sampleRange, const SampleStatistics &sampleStats, + tbb::concurrent_vector > *dataStorage, const Settings &buildSettings, bool parallel = true) const { - if(sampleRange.size() <= 0) + if (sampleRange.size() <= 0) { return; } @@ -264,13 +290,13 @@ void insertTree(KDTree &kdTree, TZeroValueSamplesContainer &samples, tbb::concur { uint32_t dataIdx = node.getDataIdx(); std::pair ®ionAndRangeData = dataStorage->operator[](dataIdx); - if(depth < buildSettings.maxDepth && regionAndRangeData.first.sampleStatistics.numSamples + sampleRange.size() > buildSettings.maxSamples) + if (depth < buildSettings.maxDepth && regionAndRangeData.first.sampleStatistics.numSamples + sampleRange.size() > buildSettings.maxSamples) { SampleStatistics mergedSampleStats = regionAndRangeData.first.sampleStatistics; - mergedSampleStats.merge( sampleStats ); + mergedSampleStats.merge(sampleStats); getSplitDimensionAndPosition(mergedSampleStats, splitDim, splitPos); - //regionAndRangeData.first.onSplit(); + // regionAndRangeData.first.onSplit(); auto regionAndRangeDataRight = regionAndRangeData; // merge split handling @@ -287,19 +313,19 @@ void insertTree(KDTree &kdTree, TZeroValueSamplesContainer &samples, tbb::concur uint32_t rightDataIdx = std::distance(dataStorage->begin(), rightDataItr); - //we need to split the leaf node + // we need to split the leaf node nodeIdsLeftRight[0] = kdTree->addChildrenPair(); nodeIdsLeftRight[1] = nodeIdsLeftRight[0] + 1; node.setToInnerNode(splitDim, splitPos, nodeIdsLeftRight[0]); kdTree->getNode(nodeIdsLeftRight[0]).setDataNodeIdx(dataIdx); kdTree->getNode(nodeIdsLeftRight[1]).setDataNodeIdx(rightDataIdx); - OPENPGL_ASSERT( kdTree->getNode(nodeIdsLeftRight[0]).isLeaf() ); - OPENPGL_ASSERT( kdTree->getNode(nodeIdsLeftRight[1]).isLeaf() ); + OPENPGL_ASSERT(kdTree->getNode(nodeIdsLeftRight[0]).isLeaf()); + OPENPGL_ASSERT(kdTree->getNode(nodeIdsLeftRight[1]).isLeaf()); } else { - regionAndRangeData.first.sampleStatistics.merge( sampleStats ); + regionAndRangeData.first.sampleStatistics.merge(sampleStats); regionAndRangeData.second = sampleRange; return; } @@ -312,8 +338,8 @@ void insertTree(KDTree &kdTree, TZeroValueSamplesContainer &samples, tbb::concur nodeIdsLeftRight[1] = nodeIdsLeftRight[0] + 1; } - OPENPGL_ASSERT( !node.isLeaf() ); - OPENPGL_ASSERT (sampleRange.size() > 0); + OPENPGL_ASSERT(!node.isLeaf()); + OPENPGL_ASSERT(sampleRange.size() > 0); // TODO: update sample stats sampleStatsLeftRight[0].clear(); sampleStatsLeftRight[1].clear(); @@ -322,20 +348,21 @@ void insertTree(KDTree &kdTree, TZeroValueSamplesContainer &samples, tbb::concur bondsLeftRight[0].upper[splitDim] = splitPos; bondsLeftRight[1].lower[splitDim] = splitPos; -#ifdef USE_EMBREE_PARALLEL +#ifdef USE_EMBREE_PARALLEL size_t rPivotItr = 0; #else typename TSamplesContainer::iterator rPivotItr(nullptr); auto begin = samples.begin() + sampleRange.m_begin, end = samples.begin() + sampleRange.m_end; #endif - if(kdTree->getNode(nodeIdsLeftRight[0]).isLeaf() || kdTree->getNode(nodeIdsLeftRight[1]).isLeaf() ) + if (kdTree->getNode(nodeIdsLeftRight[0]).isLeaf() || kdTree->getNode(nodeIdsLeftRight[1]).isLeaf()) { - //splitStats = true; + // splitStats = true; #ifdef USE_EMBREE_PARALLEL #ifndef USE_INTEGER_ARITHMETIC_STATS rPivotItr = pivotSplitSamplesWithStats2(samples.data(), sampleRange.m_begin, sampleRange.m_end, splitDim, splitPos, sampleStatsLeftRight[0], sampleStatsLeftRight[1]); #else - rPivotItr = pivotSplitSamplesWithStats3(bounds, samples.data(), sampleRange.m_begin, sampleRange.m_end, splitDim, splitPos, sampleStatsLeftRight[0], sampleStatsLeftRight[1], parallel); + rPivotItr = pivotSplitSamplesWithStats3(bounds, samples.data(), sampleRange.m_begin, sampleRange.m_end, splitDim, splitPos, sampleStatsLeftRight[0], + sampleStatsLeftRight[1], parallel); #endif #else rPivotItr = pivotSplitSamplesWithStats(begin, end, splitDim, splitPos, sampleStatsLeftRight[0], sampleStatsLeftRight[1]); @@ -350,7 +377,6 @@ void insertTree(KDTree &kdTree, TZeroValueSamplesContainer &samples, tbb::concur #endif } - #ifdef USE_EMBREE_PARALLEL sampleRangeLeftRight[0] = Range(sampleRange.m_begin, rPivotItr); sampleRangeLeftRight[1] = Range(rPivotItr, sampleRange.m_end); @@ -359,14 +385,20 @@ void insertTree(KDTree &kdTree, TZeroValueSamplesContainer &samples, tbb::concur sampleRangeLeftRight[1] = Range(std::distance(samples.begin(), rPivotItr), sampleRange.m_end); #endif tbb::parallel_invoke( - [&]{updateTreeNode(kdTree, kdTree->getNode(nodeIdsLeftRight[0]), depth + 1, bondsLeftRight[0], samples, sampleRangeLeftRight[0], sampleStatsLeftRight[0], dataStorage, buildSettings, true);}, - [&]{updateTreeNode(kdTree, kdTree->getNode(nodeIdsLeftRight[1]), depth + 1, bondsLeftRight[1], samples, sampleRangeLeftRight[1], sampleStatsLeftRight[1], dataStorage, buildSettings, true);} - ); + [&] { + updateTreeNode(kdTree, kdTree->getNode(nodeIdsLeftRight[0]), depth + 1, bondsLeftRight[0], samples, sampleRangeLeftRight[0], sampleStatsLeftRight[0], dataStorage, + buildSettings, true); + }, + [&] { + updateTreeNode(kdTree, kdTree->getNode(nodeIdsLeftRight[1]), depth + 1, bondsLeftRight[1], samples, sampleRangeLeftRight[1], sampleStatsLeftRight[1], dataStorage, + buildSettings, true); + }); } - void insertTreeNode(KDTree *kdTree, KDNode &node, size_t depth, TZeroValueSamplesContainer &samples, const Range sampleRange, tbb::concurrent_vector< std::pair > *dataStorage) const + void insertTreeNode(KDTree *kdTree, KDNode &node, size_t depth, TZeroValueSamplesContainer &samples, const Range sampleRange, + tbb::concurrent_vector > *dataStorage) const { - if(sampleRange.size() == 0) + if (sampleRange.size() == 0) { return; } @@ -396,22 +428,21 @@ void insertTree(KDTree &kdTree, TZeroValueSamplesContainer &samples, tbb::concur nodeIdsLeftRight[1] = nodeIdsLeftRight[0] + 1; } - OPENPGL_ASSERT( !node.isLeaf() ); - OPENPGL_ASSERT (sampleRange.size() > 0); + OPENPGL_ASSERT(!node.isLeaf()); + OPENPGL_ASSERT(sampleRange.size() > 0); -#ifdef USE_EMBREE_PARALLEL +#ifdef USE_EMBREE_PARALLEL size_t rPivotItr = 0; #else typename TZeroValueSamplesContainer::iterator rPivotItr; auto begin = samples.begin() + sampleRange.m_begin, end = samples.begin() + sampleRange.m_end; #endif #ifdef USE_EMBREE_PARALLEL - rPivotItr = pivotSplitSamples2(samples.data(), sampleRange.m_begin, sampleRange.m_end, splitDim, splitPos); + rPivotItr = pivotSplitSamples2(samples.data(), sampleRange.m_begin, sampleRange.m_end, splitDim, splitPos); #else - rPivotItr = pivotSplitSamples(begin, end, splitDim, splitPos); + rPivotItr = pivotSplitSamples(begin, end, splitDim, splitPos); #endif - #ifdef USE_EMBREE_PARALLEL sampleRangeLeftRight[0] = Range(sampleRange.m_begin, rPivotItr); sampleRangeLeftRight[1] = Range(rPivotItr, sampleRange.m_end); @@ -420,22 +451,22 @@ void insertTree(KDTree &kdTree, TZeroValueSamplesContainer &samples, tbb::concur sampleRangeLeftRight[1] = Range(std::distance(samples.begin(), rPivotItr), sampleRange.m_end); #endif /* This assert is a sanity check which is only valid with the assumption that the number of samples grows at same pace - as the number of spatial nodes: in practice this is not the case (e.g., after many 1spp iterations) + as the number of spatial nodes: in practice this is not the case (e.g., after many 1spp iterations) */ - //OPENPGL_ASSERT(sampleRangeLeftRight[0].size() > 1); - //OPENPGL_ASSERT(sampleRangeLeftRight[1].size() > 1); + // OPENPGL_ASSERT(sampleRangeLeftRight[0].size() > 1); + // OPENPGL_ASSERT(sampleRangeLeftRight[1].size() > 1); tbb::parallel_invoke( - [&]{insertTreeNode(kdTree, kdTree->getNode(nodeIdsLeftRight[0]), depth + 1, samples, sampleRangeLeftRight[0], dataStorage);}, - [&]{insertTreeNode(kdTree, kdTree->getNode(nodeIdsLeftRight[1]), depth + 1, samples, sampleRangeLeftRight[1], dataStorage);} - ); - + [&] { + insertTreeNode(kdTree, kdTree->getNode(nodeIdsLeftRight[0]), depth + 1, samples, sampleRangeLeftRight[0], dataStorage); + }, + [&] { + insertTreeNode(kdTree, kdTree->getNode(nodeIdsLeftRight[1]), depth + 1, samples, sampleRangeLeftRight[1], dataStorage); + }); } - }; - -template +template inline std::string KDTreePartitionBuilder::toString() const { std::stringstream ss; @@ -443,7 +474,7 @@ inline std::string KDTreePartitionBuilder +template inline std::string KDTreePartitionBuilder::Settings::toString() const { std::stringstream ss; @@ -455,20 +486,19 @@ inline std::string KDTreePartitionBuilder +inline void KDTreePartitionBuilder::Settings::serialize(std::ostream &stream) const +{ + stream.write(reinterpret_cast(&minSamples), sizeof(size_t)); + stream.write(reinterpret_cast(&maxSamples), sizeof(size_t)); + stream.write(reinterpret_cast(&maxDepth), sizeof(size_t)); +} -template -inline void KDTreePartitionBuilder::Settings::serialize(std::ostream& stream)const - { - stream.write(reinterpret_cast(&minSamples), sizeof(size_t)); - stream.write(reinterpret_cast(&maxSamples), sizeof(size_t)); - stream.write(reinterpret_cast(&maxDepth), sizeof(size_t)); - } - -template -inline void KDTreePartitionBuilder::Settings::deserialize(std::istream& stream) - { - stream.read(reinterpret_cast(&minSamples), sizeof(size_t)); - stream.read(reinterpret_cast(&maxSamples), sizeof(size_t)); - stream.read(reinterpret_cast(&maxDepth), sizeof(size_t)); - } -} \ No newline at end of file +template +inline void KDTreePartitionBuilder::Settings::deserialize(std::istream &stream) +{ + stream.read(reinterpret_cast(&minSamples), sizeof(size_t)); + stream.read(reinterpret_cast(&maxSamples), sizeof(size_t)); + stream.read(reinterpret_cast(&maxDepth), sizeof(size_t)); +} +} // namespace openpgl \ No newline at end of file diff --git a/openpgl/spatial/kdtree/KDTreeStatistics.h b/openpgl/spatial/kdtree/KDTreeStatistics.h index 8b8ece5..5fd392f 100644 --- a/openpgl/spatial/kdtree/KDTreeStatistics.h +++ b/openpgl/spatial/kdtree/KDTreeStatistics.h @@ -3,23 +3,25 @@ #pragma once -#include "../../openpgl_common.h" - -#include #include +#include + +#include "../../openpgl_common.h" namespace openpgl { -struct KDTreeStatistics{ - size_t maxDepth {0}; - size_t numberOfNodes {0}; +struct KDTreeStatistics +{ + size_t maxDepth{0}; + size_t numberOfNodes{0}; size_t numberOfReservedNodes{0}; - size_t sizePerNode {0}; - size_t sizeAllNodesReserved {0}; + size_t sizePerNode{0}; + size_t sizeAllNodesReserved{0}; size_t sizeAllNodesUsed{0}; - std::string headerCSVString() const { + std::string headerCSVString() const + { const std::string separator = " , "; std::stringstream ss; ss << "KDTreeStatistics:" << separator; @@ -32,7 +34,8 @@ struct KDTreeStatistics{ return ss.str(); } - std::string toCSVString() const { + std::string toCSVString() const + { const std::string separator = " , "; std::stringstream ss; ss << " " << separator; @@ -45,17 +48,18 @@ struct KDTreeStatistics{ return ss.str(); } - std::string toString() const { + std::string toString() const + { const std::string tab = "\t"; std::stringstream ss; ss << "KDTreeStatistics: " << std::endl; ss << tab << "numberOfNodes = " << numberOfNodes << std::endl; ss << tab << "numberOfReservedNodes = " << numberOfReservedNodes << std::endl; ss << tab << "maxDepth = " << maxDepth << std::endl; - ss << tab << "sizePerNode = " << sizePerNode << " bs"< -#include -#include -#include +#include +#include +#include #include -#include #include +#include +#include +#include #include - -#include -#include - -#include +#include +#include #include "timer.h" -enum BenchType{ - HELP=0, +enum BenchType +{ + HELP = 0, INIT_FIELD, BENCH_LOOKUP, BENCH_LOOKUP_SAMPLE, NONE }; -inline bool file_exists(const std::string& file_name) +inline bool file_exists(const std::string &file_name) { std::ifstream file(file_name.c_str()); return file.good(); } -inline pgl_vec3f squareToUniformSphere(const float sampleX, const float sampleY){ +inline pgl_vec3f squareToUniformSphere(const float sampleX, const float sampleY) +{ float z = 1.0f - 2.0f * sampleY; - float r = std::sqrt(std::max(0.f,(1.0f - z*z))); + float r = std::sqrt(std::max(0.f, (1.0f - z * z))); float phi = 2.0f * M_PI * sampleX; float sinPhi = std::sin(phi); float cosPhi = std::cos(phi); @@ -49,62 +49,72 @@ inline pgl_vec3f squareToUniformSphere(const float sampleX, const float sampleY) return sample; } -struct BenchParams { - BenchType type {HELP}; - std::string field_file_name {""}; +struct BenchParams +{ + BenchType type{HELP}; + std::string field_file_name{""}; std::vector samples_file_names; - //std::string out_file_name {""}; + // std::string out_file_name {""}; - unsigned int num_threads {0}; + unsigned int num_threads{0}; - PGL_DEVICE_TYPE device_type {PGL_DEVICE_TYPE_NONE}; + PGL_DEVICE_TYPE device_type{PGL_DEVICE_TYPE_NONE}; - bool validate() { + bool validate() + { bool valid = true; - switch(type) { + switch (type) + { case HELP: break; case INIT_FIELD: if(field_file_name == ""/* || - !file_exists(field_file_name)*/) { + !file_exists(field_file_name)*/) + { std::cout << "ERROR: Field output file not set." << std::endl; valid = false; } if(samples_file_names.size() == 0 /*|| - !file_exists(samples_file_name)*/) { - std::cout << "ERROR: Samples file not set" << std::endl; + !file_exists(samples_file_name)*/) + { + std::cout << "ERROR: Samples file not set" << std::endl; valid = false; - } else { + } + else + { for (int i = 0; i < samples_file_names.size(); i++) { - if (!file_exists(samples_file_names[i])) { + if (!file_exists(samples_file_names[i])) + { std::cout << "ERROR: Samples file does not exists: " << samples_file_names[i] << std::endl; valid = false; } } } - if(device_type == PGL_DEVICE_TYPE_NONE){ + if (device_type == PGL_DEVICE_TYPE_NONE) + { std::cout << "ERROR: Device type not set." << std::endl; - valid = false; + valid = false; } break; case BENCH_LOOKUP_SAMPLE: case BENCH_LOOKUP: - if(field_file_name == "" || - !file_exists(field_file_name)) { + if (field_file_name == "" || !file_exists(field_file_name)) + { std::cout << "ERROR: Field file not set or does not exists: " << field_file_name << std::endl; valid = false; } - if(device_type == PGL_DEVICE_TYPE_NONE){ + if (device_type == PGL_DEVICE_TYPE_NONE) + { std::cout << "ERROR: Device type not set." << std::endl; - valid = false; + valid = false; } break; - + case NONE: valid = false; break; @@ -117,94 +127,131 @@ struct BenchParams { } }; -bool parseCommandLine(std::list &args, - BenchParams &benchParams) { - +bool parseCommandLine(std::list &args, BenchParams &benchParams) +{ bool collectSamples = false; - - for (auto it = args.begin(); it != args.end();) { + + for (auto it = args.begin(); it != args.end();) + { const std::string arg = *it; - if (arg == "-help") { - collectSamples = false; + if (arg == "-help") + { + collectSamples = false; benchParams.type = BenchType::HELP; - } else if (arg == "-type") { - collectSamples = false; + } + else if (arg == "-type") + { + collectSamples = false; ++it; - if(it != args.end()) + if (it != args.end()) { const std::string str_type = *it; - if(str_type == "initField") { - benchParams.type = BenchType::INIT_FIELD; - } else if(str_type == "benchLookUpSample") { + if (str_type == "initField") + { + benchParams.type = BenchType::INIT_FIELD; + } + else if (str_type == "benchLookUpSample") + { benchParams.type = BenchType::BENCH_LOOKUP_SAMPLE; - } else if(str_type == "benchLookUp") { - benchParams.type = BenchType::BENCH_LOOKUP; - } else { + } + else if (str_type == "benchLookUp") + { + benchParams.type = BenchType::BENCH_LOOKUP; + } + else + { std::cout << "ERROR: Unknown type: " << str_type << std::endl; - std::cout << " Valid types are: [initField benchLookUp benchLookUpSample] "<< std::endl; + std::cout << " Valid types are: [initField benchLookUp benchLookUpSample] " << std::endl; return false; } - } else { + } + else + { return false; } - } else if (arg == "-device") { - collectSamples = false; + } + else if (arg == "-device") + { + collectSamples = false; ++it; - if(it != args.end()) + if (it != args.end()) { const std::string str_type = *it; - if(str_type == "CPU_4") { - benchParams.device_type = PGL_DEVICE_TYPE_CPU_4; - } else if(str_type == "CPU_8") { - benchParams.device_type = PGL_DEVICE_TYPE_CPU_8; + if (str_type == "CPU_4") + { + benchParams.device_type = PGL_DEVICE_TYPE_CPU_4; + } + else if (str_type == "CPU_8") + { + benchParams.device_type = PGL_DEVICE_TYPE_CPU_8; #ifdef OPENPGL_SUPPORT_DEVICE_TYPE_CPU_16 - } else if(str_type == "CPU_16") { + } + else if (str_type == "CPU_16") + { benchParams.device_type = PGL_DEVICE_TYPE_CPU_16; -#endif - } else { +#endif + } + else + { std::cout << "ERROR: Unknown device type: " << str_type << std::endl; std::cout << " Valid types are: [CPU_4 CPU_8"; #ifdef OPENPGL_SUPPORT_DEVICE_TYPE_CPU_16 std::cout << " CPU_16"; #endif - std::cout <<"] "<< std::endl; + std::cout << "] " << std::endl; return false; } - } else { + } + else + { return false; } - }else if (arg == "-field") { - collectSamples = false; + } + else if (arg == "-field") + { + collectSamples = false; ++it; - if(it != args.end()) + if (it != args.end()) { const std::string str_field = *it; benchParams.field_file_name = str_field; - } else { + } + else + { return false; } - } else if (arg == "-samples") { - collectSamples = true; + } + else if (arg == "-samples") + { + collectSamples = true; ++it; - if(it != args.end()) + if (it != args.end()) { const std::string str_samples = *it; - benchParams.samples_file_names.push_back(str_samples); - } else { + benchParams.samples_file_names.push_back(str_samples); + } + else + { return false; } - } else if (collectSamples) { + } + else if (collectSamples) + { const std::string str_samples = *it; - benchParams.samples_file_names.push_back(str_samples); - } else if (arg == "-threads") { - collectSamples = false; + benchParams.samples_file_names.push_back(str_samples); + } + else if (arg == "-threads") + { + collectSamples = false; ++it; - if(it != args.end()) + if (it != args.end()) { const std::string str_field = *it; benchParams.num_threads = std::stoi(str_field); - } else { + } + else + { return false; } } @@ -213,13 +260,14 @@ bool parseCommandLine(std::list &args, return true; } -void print_help(){ +void print_help() +{ const std::string tab = "\t"; const std::string space = " "; std::cout << "usage openpgl_bench -type []" << std::endl; std::cout << std::endl; std::cout << "type options:" << std::endl; - std::cout << space << "initField " << tab << "Measures the time to build a guiding Field from set of samples "<< std::endl; + std::cout << space << "initField " << tab << "Measures the time to build a guiding Field from set of samples " << std::endl; std::cout << space << " " << tab << "(i.e., saved SampleStorage objects)." << std::endl; std::cout << space << " " << tab << "example:" << std::endl; std::cout << space << " " << tab << "\"openpgl_bench -type initField -samples ss0.st ss1.st -field field.gf -device CPU_4\"" << std::endl; @@ -242,79 +290,83 @@ void print_help(){ std::cout << " -threads n " << tab << "Number of n threads that should be used during the measurements." << std::endl; std::cout << std::endl; std::cout << "initField options:" << std::endl; - std::cout << " -samples " << tab << "A list of stored samples used to initialize update the Field. "<< std::endl; - std::cout << " " << tab << "Each sample set represents one training/update step/iteration. "<< std::endl; + std::cout << " -samples " << tab << "A list of stored samples used to initialize update the Field. " << std::endl; + std::cout << " " << tab << "Each sample set represents one training/update step/iteration. " << std::endl; std::cout << " -field f0 " << tab << "The file where the initialized Field is stored." << std::endl; std::cout << std::endl; std::cout << "benchLookUp | benchLookUpSample options:" << std::endl; - std::cout << " -field f0 " << tab << "The stored Field object that is loaded for the test." << std::endl; + std::cout << " -field f0 " << tab << "The stored Field object that is loaded for the test." << std::endl; std::cout << " -samples s0 " << tab << "The stored samples which positions are used for query/initialize" << std::endl; - std::cout << " " << tab << "the SurfaceSamplingDistributions."<< std::endl; + std::cout << " " << tab << "the SurfaceSamplingDistributions." << std::endl; std::cout << std::endl; } -void init_field(BenchParams &benchParams){ - +void init_field(BenchParams &benchParams) +{ int nThreads = benchParams.num_threads; - int num_threads = 0; - if (nThreads > 0){ + int num_threads = 0; + if (nThreads > 0) + { num_threads = nThreads; } std::cout << "init_field: threads = " << num_threads << std::endl; openpgl::cpp::Device device(benchParams.device_type, num_threads); - + openpgl::cpp::FieldConfig fieldSettings; fieldSettings.Init(PGL_SPATIAL_STRUCTURE_KDTREE, PGL_DIRECTIONAL_DISTRIBUTION_PARALLAX_AWARE_VMM, true, 32000); - + fieldSettings.SetDebugArgFitRegions(true); - openpgl::cpp::Field* field = new openpgl::cpp::Field(&device, fieldSettings); - - std::vector sampleStorages; - for (int i = 0; i < benchParams.samples_file_names.size(); i++){ + openpgl::cpp::Field *field = new openpgl::cpp::Field(&device, fieldSettings); - std::cout << "sampleStorage["<< i << "]: " << benchParams.samples_file_names[i]; - openpgl::cpp::SampleStorage* sampleStorage = new openpgl::cpp::SampleStorage(benchParams.samples_file_names[i]); + std::vector sampleStorages; + for (int i = 0; i < benchParams.samples_file_names.size(); i++) + { + std::cout << "sampleStorage[" << i << "]: " << benchParams.samples_file_names[i]; + openpgl::cpp::SampleStorage *sampleStorage = new openpgl::cpp::SampleStorage(benchParams.samples_file_names[i]); std::cout << "\t nSamples = " << sampleStorage->GetSizeSurface() << std::endl; sampleStorages.push_back(sampleStorage); } Timer overallTimer; overallTimer.reset(); - for (int i = 0; i < benchParams.samples_file_names.size(); i++){ - + for (int i = 0; i < benchParams.samples_file_names.size(); i++) + { Timer updateTimer; updateTimer.reset(); field->Update(*sampleStorages[i]); - std::cout << "Field::Update() stepTime: "<< updateTimer.elapsed() * 1e-3f <<"ms"<< std::endl; + std::cout << "Field::Update() stepTime: " << updateTimer.elapsed() * 1e-3f << "ms" << std::endl; } - std::cout << "Field::Update() overallTime: "<< overallTimer.elapsed() * 1e-3f <<"ms"<< std::endl; + std::cout << "Field::Update() overallTime: " << overallTimer.elapsed() * 1e-3f << "ms" << std::endl; field->Store(benchParams.field_file_name); delete field; - for (int n = 0; n < sampleStorages.size(); n++){ + for (int n = 0; n < sampleStorages.size(); n++) + { delete sampleStorages[n]; sampleStorages[n] = nullptr; } - } -void validate_field(BenchParams &benchParams){ +void validate_field(BenchParams &benchParams) +{ openpgl::cpp::Device device(benchParams.device_type); openpgl::cpp::Field field(&device, benchParams.field_file_name); bool valid = field.Validate(); } -void bench_lookup_sample(BenchParams &benchParams, bool applyCosine, bool sample){ +void bench_lookup_sample(BenchParams &benchParams, bool applyCosine, bool sample) +{ int nThreads = benchParams.num_threads; int nRepetitions = 10; - int num_threads = 0; //tbb::info::default_concurrency(); - if (nThreads > 0){ + int num_threads = 0; // tbb::info::default_concurrency(); + if (nThreads > 0) + { num_threads = nThreads; } tbb::global_control global_limit(tbb::global_control::max_allowed_parallelism, num_threads); std::cout << "num_threads = " << num_threads << std::endl; - + openpgl::cpp::Device device(benchParams.device_type); openpgl::cpp::Field field(&device, benchParams.field_file_name); openpgl::cpp::SampleStorage sampleStorage(benchParams.samples_file_names[0]); @@ -327,11 +379,11 @@ void bench_lookup_sample(BenchParams &benchParams, bool applyCosine, bool sample std::mt19937_64 gen(1337); std::uniform_real_distribution distU(0.f, 1.f); - float* samplesSurfaceU = new float[nSurfaceSamples]; - pgl_vec2f* samplesSurfaceDirectionUV = new pgl_vec2f[nSurfaceSamples]; - pgl_vec3f* sampleSurfaceNormal = new pgl_vec3f[nSurfaceSamples]; - pgl_vec3f* sampleSurfaceSampledDirection = new pgl_vec3f[nSurfaceSamples]; - pgl_vec3f* positionsSurface = new pgl_vec3f[nSurfaceSamples]; + float *samplesSurfaceU = new float[nSurfaceSamples]; + pgl_vec2f *samplesSurfaceDirectionUV = new pgl_vec2f[nSurfaceSamples]; + pgl_vec3f *sampleSurfaceNormal = new pgl_vec3f[nSurfaceSamples]; + pgl_vec3f *sampleSurfaceSampledDirection = new pgl_vec3f[nSurfaceSamples]; + pgl_vec3f *positionsSurface = new pgl_vec3f[nSurfaceSamples]; for (int i = 0; i < nSurfaceSamples; i++) { @@ -339,7 +391,7 @@ void bench_lookup_sample(BenchParams &benchParams, bool applyCosine, bool sample samplesSurfaceU[idx] = distU(gen); samplesSurfaceDirectionUV[idx].x = distU(gen); samplesSurfaceDirectionUV[idx].y = distU(gen); - sampleSurfaceNormal[idx] = squareToUniformSphere(distU(gen),distU(gen)); + sampleSurfaceNormal[idx] = squareToUniformSphere(distU(gen), distU(gen)); openpgl::cpp::SampleData sd = sampleStorage.GetSampleSurface(i); positionsSurface[idx] = sd.position; @@ -350,21 +402,20 @@ void bench_lookup_sample(BenchParams &benchParams, bool applyCosine, bool sample Timer timer; timer.reset(); int step = nSurfaceSamples / num_threads; - tbb::parallel_for( tbb::blocked_range(0,num_threads), [&](tbb::blocked_range r) - { - for (int n = r.begin(); n(0, num_threads), [&](tbb::blocked_range r) { + for (int n = r.begin(); n < r.end(); ++n) { - openpgl::cpp::SurfaceSamplingDistribution ssd(&field); - for(int m = 0; m < nRepetitions; m++) - { - int tStep = n*step; + openpgl::cpp::SurfaceSamplingDistribution ssd(&field); + for (int m = 0; m < nRepetitions; m++) + { + int tStep = n * step; for (int i = 0; i < nSurfaceSamples; i++) { - int idx = (i+tStep) % nSurfaceSamples; + int idx = (i + tStep) % nSurfaceSamples; ssd.Init(&field, positionsSurface[idx], samplesSurfaceU[idx]); - if(applyCosine) + if (applyCosine) ssd.ApplyCosineProduct(sampleSurfaceNormal[idx]); - if(sample) + if (sample) ssd.SamplePDF(samplesSurfaceDirectionUV[idx], sampleSurfaceSampledDirection[idx]); } } @@ -372,48 +423,48 @@ void bench_lookup_sample(BenchParams &benchParams, bool applyCosine, bool sample }); std::cout << "SurfaceSamplingDistribution::Init"; - if(applyCosine) + if (applyCosine) std::cout << "+ApplyCosine"; - if(sample) - std::cout << "+SamplePDF"; - std::cout << " time: "<< (timer.elapsed()/float(nSurfaceSamples*nRepetitions)) << "µs" << "\t nThreads = " << num_threads << std::endl; + if (sample) + std::cout << "+SamplePDF"; + std::cout << " time: " << (timer.elapsed() / float(nSurfaceSamples * nRepetitions)) << "µs" << "\t nThreads = " << num_threads << std::endl; } - -int main (int argc, char *argv[]) { - +int main(int argc, char *argv[]) +{ std::list args(argv, argv + argc); BenchParams benchParams; bool success = parseCommandLine(args, benchParams); success = success ? benchParams.validate() : false; - if(success){ + if (success) + { switch (benchParams.type) { - case HELP: - print_help(); - break; - - case INIT_FIELD: - init_field(benchParams); - break; - - case BENCH_LOOKUP: - bench_lookup_sample(benchParams, false, false); - break; - - case BENCH_LOOKUP_SAMPLE: - bench_lookup_sample(benchParams, true, true); - break; - - default: - print_help(); - break; - } + case HELP: + print_help(); + break; - } else { + case INIT_FIELD: + init_field(benchParams); + break; + + case BENCH_LOOKUP: + bench_lookup_sample(benchParams, false, false); + break; + + case BENCH_LOOKUP_SAMPLE: + bench_lookup_sample(benchParams, true, true); + break; - } + default: + print_help(); + break; + } + } + else + { + } return 0; } \ No newline at end of file diff --git a/tools/openpgl_bench/timer.h b/tools/openpgl_bench/timer.h index 3e39263..a6a092a 100644 --- a/tools/openpgl_bench/timer.h +++ b/tools/openpgl_bench/timer.h @@ -1,26 +1,30 @@ #pragma once #include -class Timer { -private: +class Timer +{ + private: using clock = std::chrono::high_resolution_clock; using time_point = clock::time_point; -public: - Timer() { + public: + Timer() + { reset(); } - void reset() { + void reset() + { start = clock::now(); } - double elapsed() { + double elapsed() + { time_point end = clock::now(); std::chrono::duration diff = end - start; return diff.count(); } -private: + private: time_point start; }; \ No newline at end of file diff --git a/tools/openpgl_check/openpgl_check.cpp b/tools/openpgl_check/openpgl_check.cpp index 59099fb..d1c4e35 100644 --- a/tools/openpgl_check/openpgl_check.cpp +++ b/tools/openpgl_check/openpgl_check.cpp @@ -3,12 +3,12 @@ #include -int main (int argc, char *argv[]) { - +int main(int argc, char *argv[]) +{ openpgl::cpp::Device device(PGL_DEVICE_TYPE_NONE); - //PGLFieldArguments fieldSettings; - //pglFieldArgumentsSetDefaults(fieldSettings, PGL_SPATIAL_STRUCTURE_KDTREE, PGL_DIRECTIONAL_DISTRIBUTION_PARALLAX_AWARE_VMM); - //openpgl::cpp::Field field(&device, fieldSettings); + // PGLFieldArguments fieldSettings; + // pglFieldArgumentsSetDefaults(fieldSettings, PGL_SPATIAL_STRUCTURE_KDTREE, PGL_DIRECTIONAL_DISTRIBUTION_PARALLAX_AWARE_VMM); + // openpgl::cpp::Field field(&device, fieldSettings); return 0; } \ No newline at end of file diff --git a/tools/openpgl_debug/openpgl_debug.cpp b/tools/openpgl_debug/openpgl_debug.cpp index 4dec701..60d3964 100644 --- a/tools/openpgl_debug/openpgl_debug.cpp +++ b/tools/openpgl_debug/openpgl_debug.cpp @@ -3,14 +3,15 @@ #include -#include -#include #include -#include #include +#include +#include +#include -enum DebugType{ - HELP=0, +enum DebugType +{ + HELP = 0, UPDATE_FIELD, VALIDATE_FIELD, VALIDATE_SAMPLES, @@ -21,122 +22,130 @@ enum DebugType{ NONE }; -inline bool file_exists(const std::string& file_name) +inline bool file_exists(const std::string &file_name) { std::ifstream file(file_name.c_str()); return file.good(); } -struct DebugParams { - DebugType type {NONE}; - std::string field_file_name {""}; - std::string field_file_name_comp {""}; - std::string samples_file_name {""}; - std::string samples_file_name_comp {""}; - std::string obj_out_file_name {""}; +struct DebugParams +{ + DebugType type{NONE}; + std::string field_file_name{""}; + std::string field_file_name_comp{""}; + std::string samples_file_name{""}; + std::string samples_file_name_comp{""}; + std::string obj_out_file_name{""}; - PGL_DEVICE_TYPE device_type {PGL_DEVICE_TYPE_NONE}; + PGL_DEVICE_TYPE device_type{PGL_DEVICE_TYPE_NONE}; - bool validate() { + bool validate() + { bool valid = true; - switch(type) { + switch (type) + { case HELP: break; case UPDATE_FIELD: - if(field_file_name == "" || - !file_exists(field_file_name)) { + if (field_file_name == "" || !file_exists(field_file_name)) + { std::cout << "ERROR: Field file not set or does not exists: " << field_file_name << std::endl; valid = false; } - if(samples_file_name == "" || - !file_exists(samples_file_name)) { - std::cout << "ERROR: Samples file not set or does not exists: " << samples_file_name << std::endl; + if (samples_file_name == "" || !file_exists(samples_file_name)) + { + std::cout << "ERROR: Samples file not set or does not exists: " << samples_file_name << std::endl; valid = false; } - if(device_type == PGL_DEVICE_TYPE_NONE){ + if (device_type == PGL_DEVICE_TYPE_NONE) + { std::cout << "ERROR: Device type not set." << std::endl; - valid = false; + valid = false; } break; case VALIDATE_FIELD: - if(field_file_name == "" || - !file_exists(field_file_name)) { + if (field_file_name == "" || !file_exists(field_file_name)) + { std::cout << "ERROR: Field file not set or does not exists: " << field_file_name << std::endl; valid = false; } - if(device_type == PGL_DEVICE_TYPE_NONE){ + if (device_type == PGL_DEVICE_TYPE_NONE) + { std::cout << "ERROR: Device type not set." << std::endl; - valid = false; + valid = false; } break; case VALIDATE_SAMPLES: - if(samples_file_name == "" || - !file_exists(samples_file_name)) { - std::cout << "ERROR: Samples file not set or does not exists: " << samples_file_name << std::endl; + if (samples_file_name == "" || !file_exists(samples_file_name)) + { + std::cout << "ERROR: Samples file not set or does not exists: " << samples_file_name << std::endl; valid = false; } break; case EXPORT_SAMPLES: - if(samples_file_name == "" || - !file_exists(samples_file_name)) { - std::cout << "ERROR: Samples file not set or does not exists: " << samples_file_name << std::endl; + if (samples_file_name == "" || !file_exists(samples_file_name)) + { + std::cout << "ERROR: Samples file not set or does not exists: " << samples_file_name << std::endl; valid = false; } - if(obj_out_file_name == "") { - std::cout << "ERROR: OBJ output file not set: " << obj_out_file_name << std::endl; + if (obj_out_file_name == "") + { + std::cout << "ERROR: OBJ output file not set: " << obj_out_file_name << std::endl; valid = false; } break; case COMPARE_SAMPLES: - if(samples_file_name == "" || - !file_exists(samples_file_name)) { - std::cout << "ERROR: Samples file not set or does not exists: " << samples_file_name << std::endl; + if (samples_file_name == "" || !file_exists(samples_file_name)) + { + std::cout << "ERROR: Samples file not set or does not exists: " << samples_file_name << std::endl; valid = false; } - if(samples_file_name_comp == "" || - !file_exists(samples_file_name_comp)) { - std::cout << "ERROR: Samples file not set or does not exists: " << samples_file_name_comp << std::endl; + if (samples_file_name_comp == "" || !file_exists(samples_file_name_comp)) + { + std::cout << "ERROR: Samples file not set or does not exists: " << samples_file_name_comp << std::endl; valid = false; } break; case COMPARE_FIELDS: - if(field_file_name == "" || - !file_exists(field_file_name)) { - std::cout << "ERROR: Field file not set or does not exists: " << field_file_name << std::endl; + if (field_file_name == "" || !file_exists(field_file_name)) + { + std::cout << "ERROR: Field file not set or does not exists: " << field_file_name << std::endl; valid = false; } - if(field_file_name_comp == "" || - !file_exists(field_file_name_comp)) { - std::cout << "ERROR: Field file not set or does not exists: " << field_file_name_comp << std::endl; + if (field_file_name_comp == "" || !file_exists(field_file_name_comp)) + { + std::cout << "ERROR: Field file not set or does not exists: " << field_file_name_comp << std::endl; valid = false; } - if(device_type == PGL_DEVICE_TYPE_NONE){ + if (device_type == PGL_DEVICE_TYPE_NONE) + { std::cout << "ERROR: Device type not set." << std::endl; - valid = false; + valid = false; } break; case UPDATE_COMPARE_FIELDS: - if(field_file_name == "" || - !file_exists(field_file_name)) { - std::cout << "ERROR: Field file not set or does not exists: " << field_file_name << std::endl; + if (field_file_name == "" || !file_exists(field_file_name)) + { + std::cout << "ERROR: Field file not set or does not exists: " << field_file_name << std::endl; valid = false; } - if(samples_file_name == "" || - !file_exists(samples_file_name)) { - std::cout << "ERROR: Samples file not set or does not exists: " << samples_file_name << std::endl; + if (samples_file_name == "" || !file_exists(samples_file_name)) + { + std::cout << "ERROR: Samples file not set or does not exists: " << samples_file_name << std::endl; valid = false; } - if(field_file_name_comp == "" || - !file_exists(field_file_name_comp)) { - std::cout << "ERROR: Field file not set or does not exists: " << field_file_name_comp << std::endl; + if (field_file_name_comp == "" || !file_exists(field_file_name_comp)) + { + std::cout << "ERROR: Field file not set or does not exists: " << field_file_name_comp << std::endl; valid = false; } - if(device_type == PGL_DEVICE_TYPE_NONE){ + if (device_type == PGL_DEVICE_TYPE_NONE) + { std::cout << "ERROR: Device type not set." << std::endl; - valid = false; + valid = false; } break; case NONE: @@ -151,100 +160,150 @@ struct DebugParams { } }; -bool parseCommandLine(std::list &args, - DebugParams &debugParams) { - - for (auto it = args.begin(); it != args.end();) { +bool parseCommandLine(std::list &args, DebugParams &debugParams) +{ + for (auto it = args.begin(); it != args.end();) + { const std::string arg = *it; - if (arg == "-help") { - debugParams.type = DebugType::HELP; - } else if (arg == "-type") { + if (arg == "-help") + { + debugParams.type = DebugType::HELP; + } + else if (arg == "-type") + { ++it; - if(it != args.end()) + if (it != args.end()) { const std::string str_type = *it; - if(str_type == "updateField") { - debugParams.type = DebugType::UPDATE_FIELD; - } else if(str_type == "validateField") { - debugParams.type = DebugType::VALIDATE_FIELD; - } else if(str_type == "validateSamples") { - debugParams.type = DebugType::VALIDATE_SAMPLES; - } else if(str_type == "exportSamplesToOBJ") { - debugParams.type = DebugType::EXPORT_SAMPLES; - } else if(str_type == "compareSamples") { - debugParams.type = DebugType::COMPARE_SAMPLES; - } else if(str_type == "compareFields") { - debugParams.type = DebugType::COMPARE_FIELDS; - } else if(str_type == "updateCompareFields") { - debugParams.type = DebugType::UPDATE_COMPARE_FIELDS; - } else { + if (str_type == "updateField") + { + debugParams.type = DebugType::UPDATE_FIELD; + } + else if (str_type == "validateField") + { + debugParams.type = DebugType::VALIDATE_FIELD; + } + else if (str_type == "validateSamples") + { + debugParams.type = DebugType::VALIDATE_SAMPLES; + } + else if (str_type == "exportSamplesToOBJ") + { + debugParams.type = DebugType::EXPORT_SAMPLES; + } + else if (str_type == "compareSamples") + { + debugParams.type = DebugType::COMPARE_SAMPLES; + } + else if (str_type == "compareFields") + { + debugParams.type = DebugType::COMPARE_FIELDS; + } + else if (str_type == "updateCompareFields") + { + debugParams.type = DebugType::UPDATE_COMPARE_FIELDS; + } + else + { std::cout << "ERROR: Unknown type: " << str_type << std::endl; - std::cout << " Valid types are: [updateField validateField validateSamples exportSamplesToOBJ compareSamples compareFields] "<< std::endl; + std::cout << " Valid types are: [updateField validateField validateSamples exportSamplesToOBJ compareSamples compareFields] " << std::endl; return false; } - } else { + } + else + { return false; } - } else if (arg == "-device") { + } + else if (arg == "-device") + { ++it; - if(it != args.end()) + if (it != args.end()) { const std::string str_type = *it; - if(str_type == "CPU_4") { - debugParams.device_type = PGL_DEVICE_TYPE_CPU_4; - } else if(str_type == "CPU_8") { - debugParams.device_type = PGL_DEVICE_TYPE_CPU_8; - } else { + if (str_type == "CPU_4") + { + debugParams.device_type = PGL_DEVICE_TYPE_CPU_4; + } + else if (str_type == "CPU_8") + { + debugParams.device_type = PGL_DEVICE_TYPE_CPU_8; + } + else + { std::cout << "ERROR: Unknown device type: " << str_type << std::endl; - std::cout << " Valid types are: [CPU_4 CPU_8] "<< std::endl; + std::cout << " Valid types are: [CPU_4 CPU_8] " << std::endl; return false; } - } else { + } + else + { return false; } - } else if (arg == "-field") { + } + else if (arg == "-field") + { ++it; - if(it != args.end()) + if (it != args.end()) { const std::string str_field = *it; debugParams.field_file_name = str_field; - } else { + } + else + { return false; } - } else if (arg == "-samples") { + } + else if (arg == "-samples") + { ++it; - if(it != args.end()) + if (it != args.end()) { const std::string str_samples = *it; - debugParams.samples_file_name = str_samples; - } else { + debugParams.samples_file_name = str_samples; + } + else + { return false; } - } else if (arg == "-samplesComp") { + } + else if (arg == "-samplesComp") + { ++it; - if(it != args.end()) + if (it != args.end()) { const std::string str_samples = *it; - debugParams.samples_file_name_comp = str_samples; - } else { + debugParams.samples_file_name_comp = str_samples; + } + else + { return false; } - } else if (arg == "-fieldComp") { + } + else if (arg == "-fieldComp") + { ++it; - if(it != args.end()) + if (it != args.end()) { const std::string str_samples = *it; - debugParams.field_file_name_comp = str_samples; - } else { + debugParams.field_file_name_comp = str_samples; + } + else + { return false; - } } else if (arg == "-out") { + } + } + else if (arg == "-out") + { ++it; - if(it != args.end()) + if (it != args.end()) { const std::string str_samples = *it; - debugParams.obj_out_file_name = str_samples; - } else { + debugParams.obj_out_file_name = str_samples; + } + else + { return false; } } @@ -253,7 +312,8 @@ bool parseCommandLine(std::list &args, return true; } -void print_help(){ +void print_help() +{ const std::string tab = "\t"; const std::string space = " "; std::cout << "usage openpgl_debug -type []" << std::endl; @@ -278,34 +338,36 @@ void print_help(){ std::cout << space << " " << tab << "example:" << std::endl; std::cout << space << " " << tab << "\"openpgl_debug -type compareFields -field field0.gf -fieldComp field1.gf -device CPU_4\"" << std::endl; std::cout << std::endl; - std::cout << space << "updateField " << tab << "Loads a pre-trained guiding structure (Field) and updates it using a set of samples"<< std::endl; + std::cout << space << "updateField " << tab << "Loads a pre-trained guiding structure (Field) and updates it using a set of samples" << std::endl; std::cout << space << " " << tab << "loaded from a SampleStorage object." << std::endl; std::cout << space << " " << tab << "example:" << std::endl; std::cout << space << " " << tab << "\"openpgl_debug -type updateField -field field.gf -samples ss0.st -device CPU_4\"" << std::endl; std::cout << std::endl; - std::cout << space << "updateCompareFields " << tab << "Loads a pre-trained guiding structure (Field) and updates it using a set of samples loaded from a"<< std::endl; + std::cout << space << "updateCompareFields " << tab << "Loads a pre-trained guiding structure (Field) and updates it using a set of samples loaded from a" << std::endl; std::cout << space << " " << tab << "SampleStorage object and compares the resulting guiding structure to another pre-trained Field." << std::endl; std::cout << space << " " << tab << "example:" << std::endl; - std::cout << space << " " << tab << "\"openpgl_debug -type updateCompareFields -field field0.gf -samples ss0.st -fieldComp field1.gf -device CPU_4\"" << std::endl; + std::cout << space << " " << tab << "\"openpgl_debug -type updateCompareFields -field field0.gf -samples ss0.st -fieldComp field1.gf -device CPU_4\"" + << std::endl; std::cout << std::endl; - std::cout << space << "exportSamplesToOBJ " << tab << "Loads samples from a SampleStorage object and stores them as \".obj\" file."<< std::endl; + std::cout << space << "exportSamplesToOBJ " << tab << "Loads samples from a SampleStorage object and stores them as \".obj\" file." << std::endl; std::cout << space << " " << tab << "example:" << std::endl; std::cout << space << " " << tab << "\"openpgl_debug -type exportSamplesToOBJ -samples ss0.st -out ss0.obj\"" << std::endl; std::cout << std::endl; } -void update_field(DebugParams &debugParams){ +void update_field(DebugParams &debugParams) +{ openpgl::cpp::Device device(debugParams.device_type); openpgl::cpp::Field field(&device, debugParams.field_file_name); openpgl::cpp::SampleStorage sampleStorage(debugParams.samples_file_name); std::cout << "Validate Field:" << std::endl; bool fieldValid = field.Validate(); - std::cout << " -field: "<< debugParams.field_file_name << " is " << (fieldValid ? "valid": "NOT valid") << std::endl; + std::cout << " -field: " << debugParams.field_file_name << " is " << (fieldValid ? "valid" : "NOT valid") << std::endl; std::cout << "Validate Samples:" << std::endl; bool samplesValidate = sampleStorage.Validate(); - std::cout << " -samples: "<< debugParams.samples_file_name << " is " << (samplesValidate ? "valid" : "NOT valid") << std::endl; + std::cout << " -samples: " << debugParams.samples_file_name << " is " << (samplesValidate ? "valid" : "NOT valid") << std::endl; field.Update(sampleStorage); std::cout << "Validate Updated Field:" << std::endl; @@ -313,55 +375,60 @@ void update_field(DebugParams &debugParams){ std::cout << " updated field: is " << (fieldUpdatedValid ? "valid" : "NOT valid") << std::endl; } -void validate_field(DebugParams &debugParams){ +void validate_field(DebugParams &debugParams) +{ openpgl::cpp::Device device(debugParams.device_type); openpgl::cpp::Field field(&device, debugParams.field_file_name); std::cout << "Validate Field:" << std::endl; bool fieldValid = field.Validate(); - std::cout << " -field: "<< debugParams.field_file_name << " is "<< (fieldValid ? "valid": "NOT valid") << std::endl; + std::cout << " -field: " << debugParams.field_file_name << " is " << (fieldValid ? "valid" : "NOT valid") << std::endl; } -void validate_samples(DebugParams &debugParams){ +void validate_samples(DebugParams &debugParams) +{ openpgl::cpp::SampleStorage sampleStorage(debugParams.samples_file_name); std::cout << "Validate Samples:" << std::endl; bool samplesValid = sampleStorage.Validate(); - std::cout << " -samples: "<< debugParams.samples_file_name << " is "<< (samplesValid ? "valid" : "NOT valid") << std::endl; + std::cout << " -samples: " << debugParams.samples_file_name << " is " << (samplesValid ? "valid" : "NOT valid") << std::endl; } -void compare_samples(DebugParams &debugParams){ +void compare_samples(DebugParams &debugParams) +{ openpgl::cpp::SampleStorage sampleStorage(debugParams.samples_file_name); openpgl::cpp::SampleStorage sampleStorageComp(debugParams.samples_file_name_comp); std::cout << "Validate Samples:" << std::endl; bool samplesValid = sampleStorage.Validate(); - std::cout << " -samples: "<< debugParams.samples_file_name << " is " << (samplesValid ? "valid" : "NOT valid") << std::endl; + std::cout << " -samples: " << debugParams.samples_file_name << " is " << (samplesValid ? "valid" : "NOT valid") << std::endl; bool samplesCompValid = sampleStorageComp.Validate(); - std::cout << " -samplesComp: "<< debugParams.samples_file_name_comp << " is " << (samplesCompValid ? "valid" : "NOT valid")<< std::endl; + std::cout << " -samplesComp: " << debugParams.samples_file_name_comp << " is " << (samplesCompValid ? "valid" : "NOT valid") << std::endl; std::cout << "Compare Samples:" << std::endl; bool equal = (sampleStorage.operator==(sampleStorageComp)); - std::cout << " Samples are: "<< (equal ? "EQUAL" : "NOT-EQUAL") << std::endl; + std::cout << " Samples are: " << (equal ? "EQUAL" : "NOT-EQUAL") << std::endl; } -void compare_fields(DebugParams &debugParams){ +void compare_fields(DebugParams &debugParams) +{ openpgl::cpp::Device device(debugParams.device_type); openpgl::cpp::Field field(&device, debugParams.field_file_name); openpgl::cpp::Field fieldComp(&device, debugParams.field_file_name_comp); std::cout << "Validate Fields:" << std::endl; bool fieldValid = field.Validate(); - std::cout << " -field: "<< debugParams.field_file_name << " is "<< (fieldValid ? "valid" : "NOT valid") << std::endl; + std::cout << " -field: " << debugParams.field_file_name << " is " << (fieldValid ? "valid" : "NOT valid") << std::endl; bool fieldCompValid = fieldComp.Validate(); - std::cout << " -fieldComp: "<< debugParams.field_file_name_comp << " is "<< (fieldCompValid ? "valid": "NOT valid") << std::endl; + std::cout << " -fieldComp: " << debugParams.field_file_name_comp << " is " << (fieldCompValid ? "valid" : "NOT valid") << std::endl; std::cout << "Compare Fields:" << std::endl; bool equal = (field.operator==(fieldComp)); - std::cout << " Fields are: "<< (equal ? "EQUAL": "NOT-EQUAL") << std::endl; + std::cout << " Fields are: " << (equal ? "EQUAL" : "NOT-EQUAL") << std::endl; } -void update_compare_fields(DebugParams &debugParams){ +void update_compare_fields(DebugParams &debugParams) +{ openpgl::cpp::Device device(debugParams.device_type); openpgl::cpp::Field field(&device, debugParams.field_file_name); openpgl::cpp::SampleStorage sampleStorage(debugParams.samples_file_name); @@ -369,15 +436,14 @@ void update_compare_fields(DebugParams &debugParams){ std::cout << "Validate Fields:" << std::endl; bool fieldValid = field.Validate(); - std::cout << " -field: "<< debugParams.field_file_name << " is " << (fieldValid ? "valid": "NOT valid") << std::endl; + std::cout << " -field: " << debugParams.field_file_name << " is " << (fieldValid ? "valid" : "NOT valid") << std::endl; bool fieldCompValid = fieldComp.Validate(); - std::cout << " -fieldComp: "<< debugParams.field_file_name_comp << " is " << (fieldCompValid ? "valid": "NOT valid") << std::endl; + std::cout << " -fieldComp: " << debugParams.field_file_name_comp << " is " << (fieldCompValid ? "valid" : "NOT valid") << std::endl; std::cout << "Validate Samples:" << std::endl; bool samplesValidate = sampleStorage.Validate(); - std::cout << " -samples: "<< debugParams.samples_file_name << " is " << (samplesValidate ? "valid" : "NOT valid") << std::endl; - + std::cout << " -samples: " << debugParams.samples_file_name << " is " << (samplesValidate ? "valid" : "NOT valid") << std::endl; field.Update(sampleStorage); std::cout << "Validate Updated Field:" << std::endl; @@ -389,31 +455,31 @@ void update_compare_fields(DebugParams &debugParams){ std::cout << " Fields are: " << (equal ? "EQUAL" : "NOT-EQUAL") << std::endl; } -void export_samples(DebugParams &debugParams){ - +void export_samples(DebugParams &debugParams) +{ std::cout << "Export Samples as OBJ:" << std::endl; std::cout << " -samples " << debugParams.samples_file_name << std::endl; std::cout << " -out " << debugParams.obj_out_file_name << std::endl; std::ofstream objFile; objFile.open(debugParams.obj_out_file_name.c_str()); - + openpgl::cpp::SampleStorage sampleStorage(debugParams.samples_file_name); bool pointsOnly = true; std::vector subSampledData; subSampledData.reserve(sampleStorage.GetSizeSurface() + sampleStorage.GetSizeVolume()); - for (size_t i =0; i < sampleStorage.GetSizeSurface(); i++) + for (size_t i = 0; i < sampleStorage.GetSizeSurface(); i++) { subSampledData.push_back(sampleStorage.GetSampleSurface(i)); } - for (size_t i =0; i < sampleStorage.GetSizeVolume(); i++) + for (size_t i = 0; i < sampleStorage.GetSizeVolume(); i++) { subSampledData.push_back(sampleStorage.GetSampleVolume(i)); } - for (auto& sample : subSampledData) + for (auto &sample : subSampledData) { - objFile << "v " << sample.position.x << "\t" << sample.position.y << "\t"<< sample.position.z << std::endl; + objFile << "v " << sample.position.x << "\t" << sample.position.y << "\t" << sample.position.z << std::endl; if (!pointsOnly) { #ifdef OPENPGL_DIRECTION_COMPRESSION @@ -426,23 +492,23 @@ void export_samples(DebugParams &debugParams){ pos2.x = samplePosition.x + dir.x * sample.distance; pos2.y = samplePosition.y + dir.y * sample.distance; pos2.z = samplePosition.z + dir.z * sample.distance; - objFile << "v " << pos2.x << "\t" << pos2.y << "\t"<< pos2.z << std::endl; - objFile << "v " << sample.position.x << "\t" << sample.position.y << "\t"<< sample.position.z << std::endl; + objFile << "v " << pos2.x << "\t" << pos2.y << "\t" << pos2.z << std::endl; + objFile << "v " << sample.position.x << "\t" << sample.position.y << "\t" << sample.position.z << std::endl; } } - for (auto& sample : subSampledData) + for (auto &sample : subSampledData) { #ifdef OPENPGL_DIRECTION_COMPRESSION pgl_vec3f dir = openpgl::cpp::DecompressDirection(sample.direction); #else pgl_vec3f dir = sample.direction; #endif - objFile << "vn " << dir.x << "\t" << dir.y << "\t"<< dir.z << std::endl; + objFile << "vn " << dir.x << "\t" << dir.y << "\t" << dir.z << std::endl; if (!pointsOnly) { - objFile << "vn " << dir.x << "\t" << dir.y << "\t"<< dir.z << std::endl; - objFile << "vn " << dir.x << "\t" << dir.y << "\t"<< dir.z << std::endl; + objFile << "vn " << dir.x << "\t" << dir.y << "\t" << dir.z << std::endl; + objFile << "vn " << dir.x << "\t" << dir.y << "\t" << dir.z << std::endl; } } @@ -450,58 +516,59 @@ void export_samples(DebugParams &debugParams){ { for (int i = 0; i < subSampledData.size(); i++) { - objFile << "f " << i*3+1 << "\t" << i*3+2 << "\t"<< i*3+3 << std::endl; + objFile << "f " << i * 3 + 1 << "\t" << i * 3 + 2 << "\t" << i * 3 + 3 << std::endl; } } objFile.close(); } - -int main (int argc, char *argv[]) { - +int main(int argc, char *argv[]) +{ std::list args(argv, argv + argc); DebugParams debugParams; bool success = parseCommandLine(args, debugParams); success = success ? debugParams.validate() : false; - if(success){ + if (success) + { switch (debugParams.type) { - case HELP: - print_help(); - break; - - case UPDATE_FIELD: - update_field(debugParams); - break; - - case VALIDATE_FIELD: - validate_field(debugParams); - break; - - case VALIDATE_SAMPLES: - validate_samples(debugParams); - break; - case EXPORT_SAMPLES: - export_samples(debugParams); - break; - case COMPARE_SAMPLES: - compare_samples(debugParams); - break; - case COMPARE_FIELDS: - compare_fields(debugParams); - break; - case UPDATE_COMPARE_FIELDS: - update_compare_fields(debugParams); - break; - default: - print_help(); - break; - } - } else { + case HELP: + print_help(); + break; + + case UPDATE_FIELD: + update_field(debugParams); + break; + + case VALIDATE_FIELD: + validate_field(debugParams); + break; - } + case VALIDATE_SAMPLES: + validate_samples(debugParams); + break; + case EXPORT_SAMPLES: + export_samples(debugParams); + break; + case COMPARE_SAMPLES: + compare_samples(debugParams); + break; + case COMPARE_FIELDS: + compare_fields(debugParams); + break; + case UPDATE_COMPARE_FIELDS: + update_compare_fields(debugParams); + break; + default: + print_help(); + break; + } + } + else + { + } return 0; } \ No newline at end of file