source: trunk/src/core/random.cc @ 338

Last change on this file since 338 was 319, checked in by epyon, 11 years ago
  • created core module and moved all free source files there
  • took the opportunity to update all copyright lines and minor cleanup
  • minor fixes
  • not all examples are up to date
File size: 7.7 KB
Line 
1// Copyright (C) 2012-2014 ChaosForge Ltd
2// http://chaosforge.org/
3//
4// This file is part of NV Libraries.
5// For conditions of distribution and use, see copyright notice in nv.hh
6
7#include "nv/core/random.hh"
8#include "nv/core/time.hh"
9
10using namespace nv;
11
12random::random( random::seed_type seed /*= 0 */ )
13        : rng( seed == 0 ? randomized_seed() : seed )
14{
15       
16}
17
18random::seed_type random::randomize()
19{
20        seed_type seed = randomized_seed();
21        rng.seed( seed );
22        return seed;
23}
24
25void random::set_seed( random::seed_type seed /*= 0 */ )
26{
27        rng.seed( seed == 0 ? randomized_seed() : seed );
28}
29
30nv::random& random::get()
31{
32        static random default_rng;
33        return default_rng;
34}
35
36random::result_type random::rand()
37{
38        return rng();
39}
40
41sint32 random::srand( sint32 val )
42{
43        std::uniform_int_distribution<sint32> dist( 0, val - 1 );
44        return dist( rng );
45}
46
47uint32 random::urand( uint32 val )
48{
49        std::uniform_int_distribution<uint32> dist( 0, val - 1 );
50        return dist( rng );
51}
52
53f32 random::frand( f32 val )
54{
55        std::uniform_real_distribution<f32> dist( 0, val );
56        return dist( rng );
57}
58
59sint32 random::srange( sint32 min, sint32 max )
60{
61        std::uniform_int_distribution<sint32> dist( min, max );
62        return dist( rng );
63}
64
65uint32 random::urange( uint32 min, uint32 max )
66{
67        std::uniform_int_distribution<uint32> dist( min, max );
68        return dist( rng );
69}
70
71f32 random::frange( f32 min, f32 max )
72{
73        std::uniform_real_distribution<f32> dist( min, max );
74        return dist( rng );
75}
76
77uint32 random::dice( uint32 count, uint32 sides )
78{
79        std::uniform_int_distribution<uint32> dist( 1, sides );
80        uint32 result = 0;
81        while (count-- > 0)
82        {
83                result += dist( rng );
84        };
85        return result;
86}
87
88random::seed_type random::randomized_seed()
89{
90        return narrow_cast< seed_type >( get_ticks() );
91}
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 TracBrowser for help on using the repository browser.