www.pudn.com > ZFXMath-latest.zip > NRook.h
/// \file
///
/// \if DE
/// @brief GenerateSamples
/// \else
/// @brief GenerateSamples
/// \endif
#ifndef _ZFXMATH_INCLUDE_NROOK_H_
#define _ZFXMATH_INCLUDE_NROOK_H_
namespace ZFXMath
{
namespace SphericalHarmonics
{
/// \if DE
/// @brief GenerateSamples
/// \else
/// @brief GenerateSamples
///
/// Method of uniformly distributing samples over a sphere
/// From ACM Journal of Graphics Tools (http://www.acm.org/jgt)
/// Thanks for Robin Green for suggestion
/// \endif
template
SphericalHarmonics::TSample* GenerateSamples( const int nb_samples )
{
// Generate nrook cells
int* cells = new int[nb_samples];
for (int i = 0; i < nb_samples; i++)
cells[i] = i;
MultiStageNRooks(nb_samples, cells);
// Allocate the samples list
SphericalHarmonics::TSample* samples = new SphericalHarmonics::TSample[nb_samples];
for (int i = 0; i < nb_samples; i++)
{
// Generate uniform random sample
PrecisionType x = (i + drand48()) / nb_samples;
PrecisionType y = (cells[i] + drand48()) / nb_samples;
// Generate spherical/cartesian co-ordinates
samples[i] = SphericalHarmonics::TSample( PrecisionType( 2 * acos(sqrt(1 - x)) ), PrecisionType( 2 * PI * y ) );
}
delete [] cells;
return samples;
}
template
PrecisionType drand48()
{
return ((PrecisionType)rand() / RAND_MAX);
}
int lrand48()
{
return (rand());
}
template
void MultiStageNRooks(const int size, int* cells)
{
if (size == 1)
return;
int size1 = size >> 1;
int size2 = size >> 1;
if (size & 1)
{
if (drand48() > 0.5)
size1++;
else
size2++;
}
int* upper_cells = new int[size1];
int* lower_cells = new int[size2];
for (int i = 0, j = 0; i < size - 1; i += 2, j++)
{
if (lrand48() & 1)
{
upper_cells[j] = cells[i];
lower_cells[j] = cells[i + 1];
}
else
{
upper_cells[j] = cells[i + 1];
lower_cells[j] = cells[i];
}
}
if (size1 != size2)
{
if (size1 > size2)
upper_cells[j] = cells[i];
else
lower_cells[j] = cells[i];
}
MultiStageNRooks(size1, upper_cells);
memcpy(cells, upper_cells, size1 * sizeof(int));
delete [] upper_cells;
MultiStageNRooks(size2, lower_cells);
memcpy(cells + size1, lower_cells, size2 * sizeof(int));
delete [] lower_cells;
}
}; // namespace SphericalHarmonics
}; // namespace ZFXMath
#endif //_ZFXMATH_INCLUDE_NROOK_H_