Changeset 308 for trunk/src/random.cc


Ignore:
Timestamp:
08/12/14 20:34:31 (11 years ago)
Author:
epyon
Message:
  • multiple heavy duty functions added for random uniform distribution on: circles spheres disks spheroids hollow versions of all of the above
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/random.cc

    r199 r308  
    9090        return narrow_cast< seed_type >( get_ticks() );
    9191}
     92
     93nv::vec2 nv::random::precise_unit_vec2()
     94{
     95        std::uniform_real_distribution<f32> dist( 0, glm::pi<float>() * 2.f );
     96        float angle = dist( rng );
     97        return vec2( glm::cos( angle ), glm::sin( angle ) );
     98}
     99
     100nv::vec3 nv::random::precise_unit_vec3()
     101{
     102        std::uniform_real_distribution<f32> dist11( -1.0f, 1.0f );
     103        std::uniform_real_distribution<f32> dist02pi( 0.0f, 2*glm::pi<float>() );
     104        float cos_theta = dist11( rng );
     105        float sin_theta = glm::sqrt( 1.0f - cos_theta * cos_theta );
     106        float phi       = dist02pi( rng );
     107        return vec3(
     108                sin_theta * glm::sin(phi),
     109                sin_theta * glm::cos(phi),
     110                cos_theta
     111                );
     112}
     113
     114nv::vec2 nv::random::fast_disk_point()
     115{
     116        std::uniform_real_distribution<f32> dist( 0.0f, 1.0f );
     117        float r1 = dist( rng );
     118        float r2 = dist( rng );
     119        if ( r1 > r2 ) std::swap( r1, r2 );
     120        float rf = 2*glm::pi<float>()*(r1/r2);
     121        return vec2( r2*glm::cos( rf ), r2*glm::sin( rf ) );
     122}
     123
     124nv::vec2 nv::random::precise_disk_point()
     125{
     126        std::uniform_real_distribution<f32> unit( 0.0f, 1.0f );
     127        std::uniform_real_distribution<f32> angle( 0.0f, glm::pi<float>() );
     128        float r = glm::sqrt( unit( rng ) );
     129        float rangle = angle( rng );
     130        return vec2( r*glm::cos( rangle ), r*glm::sin( rangle ) );
     131}
     132
     133nv::vec3 nv::random::fast_sphere_point()
     134{
     135        std::uniform_real_distribution<f32> dist01( 0.0f, 1.0f );
     136        std::uniform_real_distribution<f32> dist11( -1.0f, 1.0f );
     137        std::uniform_real_distribution<f32> dist02pi( 0.0f, 2*glm::pi<float>() );
     138        float rad     = dist01( rng );
     139        float pi      = glm::pi<float>();
     140        float phi     = glm::asin( dist11( rng ) ) + pi*.5f;
     141        float theta   = dist02pi( rng );
     142        float sin_phi = glm::sin( phi );
     143        return vec3(
     144                rad * glm::cos(theta) * sin_phi,
     145                rad * glm::sin(theta) * sin_phi,
     146                rad * glm::cos(phi)
     147        );
     148}
     149
     150nv::vec3 nv::random::precise_sphere_point()
     151{
     152        std::uniform_real_distribution<f32> dist01( 0.0f, 1.0f );
     153        std::uniform_real_distribution<f32> dist11( -1.0f, 1.0f );
     154        std::uniform_real_distribution<f32> dist02pi( 0.0f, 2*glm::pi<float>() );
     155        float radius = std::pow( dist01( rng ), 1.f/3.f );
     156        float cos_theta = dist11( rng );
     157        float sin_theta = glm::sqrt( 1.0f - cos_theta * cos_theta );
     158        float phi       = dist02pi( rng );
     159        return vec3(
     160                radius * sin_theta * glm::sin(phi),
     161                radius * sin_theta * glm::cos(phi),
     162                radius * cos_theta
     163                );
     164}
     165
     166nv::vec2 nv::random::precise_ellipse_point( const vec2& radii )
     167{
     168        std::uniform_real_distribution<f32> distx( -radii.x, radii.x );
     169        std::uniform_real_distribution<f32> disty( -radii.y, radii.y );
     170        vec2 inv_radii  = 1.f / radii;
     171        vec2 inv_radii2 = inv_radii * inv_radii;
     172        for ( uint32 i = 0; i < 12; ++i )
     173        {
     174                float x = distx( rng );
     175                float y = disty( rng );
     176                if ( x * x * inv_radii2.x + y * y * inv_radii2.y <= 1.f )
     177                {
     178                        return vec2( x, y );
     179                }
     180        }
     181        return fast_disk_point() * radii;
     182}
     183
     184nv::vec3 nv::random::precise_ellipsoid_point( const vec3& radii )
     185{
     186        std::uniform_real_distribution<f32> distx( -radii.x, radii.x );
     187        std::uniform_real_distribution<f32> disty( -radii.y, radii.y );
     188        std::uniform_real_distribution<f32> distz( -radii.z, radii.z );
     189        vec3 inv_radii  = 1.f / radii;
     190        vec3 inv_radii2 = inv_radii * inv_radii;
     191        for ( uint32 i = 0; i < 12; ++i )
     192        {
     193                float x = distx( rng );
     194                float y = disty( rng );
     195                float z = distz( rng );
     196                if ( x * x * inv_radii2.x + y * y * inv_radii2.y + z * z * inv_radii2.z <= 1.f )
     197                {
     198                        return vec3( x, y, z );
     199                }
     200        }
     201        return fast_sphere_point() * radii;
     202}
     203
     204nv::vec2 nv::random::fast_hollow_disk_point( float iradius, float oradius )
     205{
     206        float idist2 = iradius * iradius;
     207        float odist2 = oradius * oradius;
     208        float rdist  = glm::sqrt( std::uniform_real_distribution<f32>( idist2, odist2 )( rng ) );
     209        return rdist * precise_unit_vec2();
     210}
     211
     212nv::vec2 nv::random::precise_hollow_disk_point( float iradius, float oradius )
     213{
     214        return fast_hollow_disk_point( iradius, oradius );
     215}
     216
     217nv::vec3 nv::random::fast_hollow_sphere_point( float iradius, float oradius )
     218{
     219        float idist3 = iradius * iradius * iradius;
     220        float odist3 = oradius * oradius * oradius;
     221        float rdist  = std::pow( std::uniform_real_distribution<f32>( idist3, odist3 )( rng ), 1.f/3.f );
     222        return rdist * precise_unit_vec3();
     223}
     224
     225nv::vec3 nv::random::precise_hollow_sphere_point( float iradius, float oradius )
     226{
     227        return fast_hollow_sphere_point( iradius, oradius );
     228}
     229
     230
     231nv::vec2 nv::random::fast_hollow_ellipse_point( const vec2& iradii, const vec2& oradii )
     232{
     233        vec2 iradii2    = iradii * iradii;
     234        vec2 opoint     = ellipse_edge( oradii );
     235        vec2 opoint2    = opoint * opoint;
     236        vec2 odir       = glm::normalize( opoint );
     237        float odist2    = opoint2.x + opoint2.y;
     238
     239        float low    = iradii2.y * opoint2.x + iradii2.x * opoint2.y;
     240        float idist2 = ((iradii2.x * iradii2.y) / low ) * odist2;
     241
     242        float rdist     = glm::sqrt( std::uniform_real_distribution<f32>( idist2, odist2 )( rng ) );
     243        return odir * rdist;   
     244}
     245
     246nv::vec2 nv::random::precise_hollow_ellipse_point( const vec2& iradii, const vec2& oradii )
     247{
     248        return fast_hollow_ellipse_point( iradii, oradii );
     249}
     250
     251nv::vec3 nv::random::fast_hollow_ellipsoid_point( const vec3& iradii, const vec3& oradii )
     252{
     253        vec3 iradii2    = iradii * iradii;
     254        vec3 opoint     = ellipsoid_edge( oradii );
     255        vec3 opoint2    = opoint * opoint;
     256        vec3 odir       = glm::normalize( opoint );
     257        float odist2    = opoint2.x + opoint2.y + opoint2.z;
     258
     259        float low    =
     260                iradii2.y * iradii2.z * opoint2.x +
     261                iradii2.x * iradii2.z * opoint2.y +
     262                iradii2.x * iradii2.y * opoint2.z;
     263        float idist2 = ((iradii2.x * iradii2.y * iradii2.z) / low ) * odist2;
     264
     265        float odist3 = odist2 * glm::sqrt( odist2 );
     266        float idist3 = idist2 * glm::sqrt( idist2 );
     267
     268        float rdist     = std::pow( std::uniform_real_distribution<f32>( idist3, odist3 )( rng ), 1.f/3.f );
     269        return odir * rdist;   
     270}
     271
     272nv::vec3 nv::random::precise_hollow_ellipsoid_point( const vec3& iradii, const vec3& oradii )
     273{
     274        return fast_hollow_ellipsoid_point( iradii, oradii );
     275}
     276
Note: See TracChangeset for help on using the changeset viewer.