| 128 | } |
| 129 | |
| 130 | void merge(const SampleStatistics &b) |
| 131 | { |
| 132 | if (numSamples + b.numSamples == 0) |
| 133 | { |
| 134 | return; |
| 135 | } |
| 136 | |
| 137 | const Point3 meanA = mean; |
| 138 | const Point3 meanB = b.mean; |
| 139 | |
| 140 | const Vector3 varianceA = variance; |
| 141 | const Vector3 varianceB = b.variance; |
| 142 | |
| 143 | const float numSamplesA = numSamples; |
| 144 | const float numSamplesB = b.numSamples; |
| 145 | |
| 146 | const float weightA = numSamplesA / (numSamplesA + numSamplesB); |
| 147 | const float weightB = 1.0f - weightA; |
| 148 | mean = meanA * weightA + meanB * weightB; |
| 149 | numSamples += numSamplesB; |
| 150 | |
| 151 | // Simple version to calculate the variance of two merged distributions |
| 152 | // variance = (weightA * (varianceA + meanA * meanA) + weightB * (varianceB + meanB * meanB)) - (mean * mean); |
| 153 | // Numerical more stable version to calculate the variance of two merged distributions |
| 154 | const Point3 meanDiffA = meanA - mean; |
| 155 | const Point3 meanDiffB = meanB - mean; |
| 156 | variance = (weightA * varianceA + weightB * varianceB) + (weightA * (meanDiffA * meanDiffA) + weightB * (meanDiffB * meanDiffB)); |
| 157 | variance.x = variance.x >= 0.f ? variance.x : 0.f; |
| 158 | variance.y = variance.y >= 0.f ? variance.y : 0.f; |
| 159 | variance.z = variance.z >= 0.f ? variance.z : 0.f; |
| 160 | sampleBounds.extend(b.sampleBounds); |
| 161 | |
| 162 | numZeroValueSamples += b.numZeroValueSamples; |
| 163 | |
| 164 | OPENPGL_ASSERT(isValid()); |
| 165 | } |
| 166 | |
| 167 | inline bool isValid() const |
| 168 | { |
no test coverage detected