| 113 | // -------------------------------------------------------------------------------------------------------------------- |
| 114 | |
| 115 | ProbeVisibilityGraph::ProbeVisibilityGraph(const IScene& scene, |
| 116 | const ProbeBatch& probes, |
| 117 | const ProbeVisibilityTester& visTester, |
| 118 | float radius, |
| 119 | float threshold, |
| 120 | float visRange, |
| 121 | int numThreads, |
| 122 | JobGraph& jobGraph, |
| 123 | std::atomic<bool>& cancel, |
| 124 | ProgressCallback progressCallback, |
| 125 | void* callbackUserData) |
| 126 | : mAdjacent(probes.numProbes()) |
| 127 | , mNumJobsRemaining(0) |
| 128 | { |
| 129 | PROFILE_FUNCTION(); |
| 130 | |
| 131 | // For any 2 probe indices (i, j), we will only check visibility if i > j. |
| 132 | // We will divide the work of constructing the visibility graph into a set of jobs, where each job involves |
| 133 | // constructing one or more rows of the adjacency list (mAdjacent[i]). A given row will never be processed by |
| 134 | // multiple threads concurrently. |
| 135 | auto numProbes = probes.numProbes(); |
| 136 | auto numProbesPerJob = 1; |
| 137 | |
| 138 | auto numProbesThisJob = 0; |
| 139 | auto firstProbeThisJob = 0; |
| 140 | for (auto i = 0; i < numProbes; i++) |
| 141 | { |
| 142 | numProbesThisJob++; |
| 143 | if (numProbesThisJob == 1) |
| 144 | { |
| 145 | firstProbeThisJob = i; |
| 146 | } |
| 147 | |
| 148 | if (numProbesThisJob == numProbesPerJob || |
| 149 | i == numProbes - 1) |
| 150 | { |
| 151 | jobGraph.addJob([this, firstProbeThisJob, numProbesThisJob, radius, threshold, visRange, &scene, &probes, &visTester](int threadIndex, std::atomic<bool>& cancel) |
| 152 | { |
| 153 | for (auto i = firstProbeThisJob; i < firstProbeThisJob + numProbesThisJob; i++) |
| 154 | { |
| 155 | for (auto j = 0; j < i; ++j) |
| 156 | { |
| 157 | if (visTester.areProbesTooFar(probes, i, j, visRange)) |
| 158 | continue; |
| 159 | |
| 160 | if (!visTester.areProbesVisible(scene, probes, i, j, radius, threshold)) |
| 161 | continue; |
| 162 | |
| 163 | auto cost = (probes[i].influence.center - probes[j].influence.center).length(); |
| 164 | |
| 165 | mAdjacent[i].push_back(AdjacencyListEntry{j, cost}); |
| 166 | } |
| 167 | } |
| 168 | |
| 169 | // The last job we process "completes" the adjacency list, by making sure that if we have an edge from |
| 170 | // i to j, we also have an edge from j to i. |
| 171 | if (std::atomic_fetch_sub_explicit(&mNumJobsRemaining, 1, std::memory_order_seq_cst) == 1) |
| 172 | { |
nothing calls this directly
no test coverage detected