1/// @ref gtc_random 2/// @file glm/gtc/random.inl 3 4#include "../geometric.hpp" 5#include "../exponential.hpp" 6#include <cstdlib> 7#include <ctime> 8#include <cassert> 9 10namespace glm{ 11namespace detail 12{ 13 template <typename T, precision P, template <class, precision> class vecType> 14 struct compute_rand 15 { 16 GLM_FUNC_QUALIFIER static vecType<T, P> call(); 17 }; 18 19 template <precision P> 20 struct compute_rand<uint8, P, tvec1> 21 { 22 GLM_FUNC_QUALIFIER static tvec1<uint8, P> call() 23 { 24 return tvec1<uint8, P>( 25 std::rand() % std::numeric_limits<uint8>::max()); 26 } 27 }; 28 29 template <precision P> 30 struct compute_rand<uint8, P, tvec2> 31 { 32 GLM_FUNC_QUALIFIER static tvec2<uint8, P> call() 33 { 34 return tvec2<uint8, P>( 35 std::rand() % std::numeric_limits<uint8>::max(), 36 std::rand() % std::numeric_limits<uint8>::max()); 37 } 38 }; 39 40 template <precision P> 41 struct compute_rand<uint8, P, tvec3> 42 { 43 GLM_FUNC_QUALIFIER static tvec3<uint8, P> call() 44 { 45 return tvec3<uint8, P>( 46 std::rand() % std::numeric_limits<uint8>::max(), 47 std::rand() % std::numeric_limits<uint8>::max(), 48 std::rand() % std::numeric_limits<uint8>::max()); 49 } 50 }; 51 52 template <precision P> 53 struct compute_rand<uint8, P, tvec4> 54 { 55 GLM_FUNC_QUALIFIER static tvec4<uint8, P> call() 56 { 57 return tvec4<uint8, P>( 58 std::rand() % std::numeric_limits<uint8>::max(), 59 std::rand() % std::numeric_limits<uint8>::max(), 60 std::rand() % std::numeric_limits<uint8>::max(), 61 std::rand() % std::numeric_limits<uint8>::max()); 62 } 63 }; 64 65 template <precision P, template <class, precision> class vecType> 66 struct compute_rand<uint16, P, vecType> 67 { 68 GLM_FUNC_QUALIFIER static vecType<uint16, P> call() 69 { 70 return 71 (vecType<uint16, P>(compute_rand<uint8, P, vecType>::call()) << static_cast<uint16>(8)) | 72 (vecType<uint16, P>(compute_rand<uint8, P, vecType>::call()) << static_cast<uint16>(0)); 73 } 74 }; 75 76 template <precision P, template <class, precision> class vecType> 77 struct compute_rand<uint32, P, vecType> 78 { 79 GLM_FUNC_QUALIFIER static vecType<uint32, P> call() 80 { 81 return 82 (vecType<uint32, P>(compute_rand<uint16, P, vecType>::call()) << static_cast<uint32>(16)) | 83 (vecType<uint32, P>(compute_rand<uint16, P, vecType>::call()) << static_cast<uint32>(0)); 84 } 85 }; 86 87 template <precision P, template <class, precision> class vecType> 88 struct compute_rand<uint64, P, vecType> 89 { 90 GLM_FUNC_QUALIFIER static vecType<uint64, P> call() 91 { 92 return 93 (vecType<uint64, P>(compute_rand<uint32, P, vecType>::call()) << static_cast<uint64>(32)) | 94 (vecType<uint64, P>(compute_rand<uint32, P, vecType>::call()) << static_cast<uint64>(0)); 95 } 96 }; 97 98 template <typename T, precision P, template <class, precision> class vecType> 99 struct compute_linearRand 100 { 101 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & Min, vecType<T, P> const & Max); 102 }; 103 104 template <precision P, template <class, precision> class vecType> 105 struct compute_linearRand<int8, P, vecType> 106 { 107 GLM_FUNC_QUALIFIER static vecType<int8, P> call(vecType<int8, P> const & Min, vecType<int8, P> const & Max) 108 { 109 return (vecType<int8, P>(compute_rand<uint8, P, vecType>::call() % vecType<uint8, P>(Max + static_cast<int8>(1) - Min))) + Min; 110 } 111 }; 112 113 template <precision P, template <class, precision> class vecType> 114 struct compute_linearRand<uint8, P, vecType> 115 { 116 GLM_FUNC_QUALIFIER static vecType<uint8, P> call(vecType<uint8, P> const & Min, vecType<uint8, P> const & Max) 117 { 118 return (compute_rand<uint8, P, vecType>::call() % (Max + static_cast<uint8>(1) - Min)) + Min; 119 } 120 }; 121 122 template <precision P, template <class, precision> class vecType> 123 struct compute_linearRand<int16, P, vecType> 124 { 125 GLM_FUNC_QUALIFIER static vecType<int16, P> call(vecType<int16, P> const & Min, vecType<int16, P> const & Max) 126 { 127 return (vecType<int16, P>(compute_rand<uint16, P, vecType>::call() % vecType<uint16, P>(Max + static_cast<int16>(1) - Min))) + Min; 128 } 129 }; 130 131 template <precision P, template <class, precision> class vecType> 132 struct compute_linearRand<uint16, P, vecType> 133 { 134 GLM_FUNC_QUALIFIER static vecType<uint16, P> call(vecType<uint16, P> const & Min, vecType<uint16, P> const & Max) 135 { 136 return (compute_rand<uint16, P, vecType>::call() % (Max + static_cast<uint16>(1) - Min)) + Min; 137 } 138 }; 139 140 template <precision P, template <class, precision> class vecType> 141 struct compute_linearRand<int32, P, vecType> 142 { 143 GLM_FUNC_QUALIFIER static vecType<int32, P> call(vecType<int32, P> const & Min, vecType<int32, P> const & Max) 144 { 145 return (vecType<int32, P>(compute_rand<uint32, P, vecType>::call() % vecType<uint32, P>(Max + static_cast<int32>(1) - Min))) + Min; 146 } 147 }; 148 149 template <precision P, template <class, precision> class vecType> 150 struct compute_linearRand<uint32, P, vecType> 151 { 152 GLM_FUNC_QUALIFIER static vecType<uint32, P> call(vecType<uint32, P> const & Min, vecType<uint32, P> const & Max) 153 { 154 return (compute_rand<uint32, P, vecType>::call() % (Max + static_cast<uint32>(1) - Min)) + Min; 155 } 156 }; 157 158 template <precision P, template <class, precision> class vecType> 159 struct compute_linearRand<int64, P, vecType> 160 { 161 GLM_FUNC_QUALIFIER static vecType<int64, P> call(vecType<int64, P> const & Min, vecType<int64, P> const & Max) 162 { 163 return (vecType<int64, P>(compute_rand<uint64, P, vecType>::call() % vecType<uint64, P>(Max + static_cast<int64>(1) - Min))) + Min; 164 } 165 }; 166 167 template <precision P, template <class, precision> class vecType> 168 struct compute_linearRand<uint64, P, vecType> 169 { 170 GLM_FUNC_QUALIFIER static vecType<uint64, P> call(vecType<uint64, P> const & Min, vecType<uint64, P> const & Max) 171 { 172 return (compute_rand<uint64, P, vecType>::call() % (Max + static_cast<uint64>(1) - Min)) + Min; 173 } 174 }; 175 176 template <template <class, precision> class vecType> 177 struct compute_linearRand<float, lowp, vecType> 178 { 179 GLM_FUNC_QUALIFIER static vecType<float, lowp> call(vecType<float, lowp> const & Min, vecType<float, lowp> const & Max) 180 { 181 return vecType<float, lowp>(compute_rand<uint8, lowp, vecType>::call()) / static_cast<float>(std::numeric_limits<uint8>::max()) * (Max - Min) + Min; 182 } 183 }; 184 185 template <template <class, precision> class vecType> 186 struct compute_linearRand<float, mediump, vecType> 187 { 188 GLM_FUNC_QUALIFIER static vecType<float, mediump> call(vecType<float, mediump> const & Min, vecType<float, mediump> const & Max) 189 { 190 return vecType<float, mediump>(compute_rand<uint16, mediump, vecType>::call()) / static_cast<float>(std::numeric_limits<uint16>::max()) * (Max - Min) + Min; 191 } 192 }; 193 194 template <template <class, precision> class vecType> 195 struct compute_linearRand<float, highp, vecType> 196 { 197 GLM_FUNC_QUALIFIER static vecType<float, highp> call(vecType<float, highp> const & Min, vecType<float, highp> const & Max) 198 { 199 return vecType<float, highp>(compute_rand<uint32, highp, vecType>::call()) / static_cast<float>(std::numeric_limits<uint32>::max()) * (Max - Min) + Min; 200 } 201 }; 202 203 template <template <class, precision> class vecType> 204 struct compute_linearRand<double, lowp, vecType> 205 { 206 GLM_FUNC_QUALIFIER static vecType<double, lowp> call(vecType<double, lowp> const & Min, vecType<double, lowp> const & Max) 207 { 208 return vecType<double, lowp>(compute_rand<uint16, lowp, vecType>::call()) / static_cast<double>(std::numeric_limits<uint16>::max()) * (Max - Min) + Min; 209 } 210 }; 211 212 template <template <class, precision> class vecType> 213 struct compute_linearRand<double, mediump, vecType> 214 { 215 GLM_FUNC_QUALIFIER static vecType<double, mediump> call(vecType<double, mediump> const & Min, vecType<double, mediump> const & Max) 216 { 217 return vecType<double, mediump>(compute_rand<uint32, mediump, vecType>::call()) / static_cast<double>(std::numeric_limits<uint32>::max()) * (Max - Min) + Min; 218 } 219 }; 220 221 template <template <class, precision> class vecType> 222 struct compute_linearRand<double, highp, vecType> 223 { 224 GLM_FUNC_QUALIFIER static vecType<double, highp> call(vecType<double, highp> const & Min, vecType<double, highp> const & Max) 225 { 226 return vecType<double, highp>(compute_rand<uint64, highp, vecType>::call()) / static_cast<double>(std::numeric_limits<uint64>::max()) * (Max - Min) + Min; 227 } 228 }; 229 230 template <template <class, precision> class vecType> 231 struct compute_linearRand<long double, lowp, vecType> 232 { 233 GLM_FUNC_QUALIFIER static vecType<long double, lowp> call(vecType<long double, lowp> const & Min, vecType<long double, lowp> const & Max) 234 { 235 return vecType<long double, lowp>(compute_rand<uint32, lowp, vecType>::call()) / static_cast<long double>(std::numeric_limits<uint32>::max()) * (Max - Min) + Min; 236 } 237 }; 238 239 template <template <class, precision> class vecType> 240 struct compute_linearRand<long double, mediump, vecType> 241 { 242 GLM_FUNC_QUALIFIER static vecType<long double, mediump> call(vecType<long double, mediump> const & Min, vecType<long double, mediump> const & Max) 243 { 244 return vecType<long double, mediump>(compute_rand<uint64, mediump, vecType>::call()) / static_cast<long double>(std::numeric_limits<uint64>::max()) * (Max - Min) + Min; 245 } 246 }; 247 248 template <template <class, precision> class vecType> 249 struct compute_linearRand<long double, highp, vecType> 250 { 251 GLM_FUNC_QUALIFIER static vecType<long double, highp> call(vecType<long double, highp> const & Min, vecType<long double, highp> const & Max) 252 { 253 return vecType<long double, highp>(compute_rand<uint64, highp, vecType>::call()) / static_cast<long double>(std::numeric_limits<uint64>::max()) * (Max - Min) + Min; 254 } 255 }; 256}//namespace detail 257 258 template <typename genType> 259 GLM_FUNC_QUALIFIER genType linearRand(genType Min, genType Max) 260 { 261 return detail::compute_linearRand<genType, highp, tvec1>::call( 262 tvec1<genType, highp>(Min), 263 tvec1<genType, highp>(Max)).x; 264 } 265 266 template <typename T, precision P, template <typename, precision> class vecType> 267 GLM_FUNC_QUALIFIER vecType<T, P> linearRand(vecType<T, P> const & Min, vecType<T, P> const & Max) 268 { 269 return detail::compute_linearRand<T, P, vecType>::call(Min, Max); 270 } 271 272 template <typename genType> 273 GLM_FUNC_QUALIFIER genType gaussRand(genType Mean, genType Deviation) 274 { 275 genType w, x1, x2; 276 277 do 278 { 279 x1 = linearRand(genType(-1), genType(1)); 280 x2 = linearRand(genType(-1), genType(1)); 281 282 w = x1 * x1 + x2 * x2; 283 } while(w > genType(1)); 284 285 return x2 * Deviation * Deviation * sqrt((genType(-2) * log(w)) / w) + Mean; 286 } 287 288 template <typename T, precision P, template <typename, precision> class vecType> 289 GLM_FUNC_QUALIFIER vecType<T, P> gaussRand(vecType<T, P> const & Mean, vecType<T, P> const & Deviation) 290 { 291 return detail::functor2<T, P, vecType>::call(gaussRand, Mean, Deviation); 292 } 293 294 template <typename T> 295 GLM_FUNC_QUALIFIER tvec2<T, defaultp> diskRand(T Radius) 296 { 297 tvec2<T, defaultp> Result(T(0)); 298 T LenRadius(T(0)); 299 300 do 301 { 302 Result = linearRand( 303 tvec2<T, defaultp>(-Radius), 304 tvec2<T, defaultp>(Radius)); 305 LenRadius = length(Result); 306 } 307 while(LenRadius > Radius); 308 309 return Result; 310 } 311 312 template <typename T> 313 GLM_FUNC_QUALIFIER tvec3<T, defaultp> ballRand(T Radius) 314 { 315 tvec3<T, defaultp> Result(T(0)); 316 T LenRadius(T(0)); 317 318 do 319 { 320 Result = linearRand( 321 tvec3<T, defaultp>(-Radius), 322 tvec3<T, defaultp>(Radius)); 323 LenRadius = length(Result); 324 } 325 while(LenRadius > Radius); 326 327 return Result; 328 } 329 330 template <typename T> 331 GLM_FUNC_QUALIFIER tvec2<T, defaultp> circularRand(T Radius) 332 { 333 T a = linearRand(T(0), T(6.283185307179586476925286766559f)); 334 return tvec2<T, defaultp>(cos(a), sin(a)) * Radius; 335 } 336 337 template <typename T> 338 GLM_FUNC_QUALIFIER tvec3<T, defaultp> sphericalRand(T Radius) 339 { 340 T z = linearRand(T(-1), T(1)); 341 T a = linearRand(T(0), T(6.283185307179586476925286766559f)); 342 343 T r = sqrt(T(1) - z * z); 344 345 T x = r * cos(a); 346 T y = r * sin(a); 347 348 return tvec3<T, defaultp>(x, y, z) * Radius; 349 } 350}//namespace glm 351