POV-Ray : Newsgroups : povray.text.scene-files : pseudo-random number generator : pseudo-random number generator Server Time
5 Jul 2024 10:09:47 EDT (-0400)
  pseudo-random number generator  
From: Pete
Date: 11 Aug 2001 14:31:43
Message: <5305.623T1870T6815291PeterC@nym.alias.net>
This is an attempt at a "random" number generator in povray.
I have not tested it that much but the results *look* random
to me.  The actual random number generator only works with
8 bit values so I call it four times multiply those results
to get a single float value.

Dunno if it will work under mega pov: might have to rename
some of the variables first.

Enjoy

Pete
-- 
#version 3.1;


#declare I = 0; // 1st index
#declare J = 0; // second index
#declare S = array[256] // thrash array
#declare K = array[256] // thrash init array
// this next array is where you put the starting seed.
// Put in four positive integer numbers, each in the
// range 0 to 99999999.
#declare thrash_seed = array[4]{
  68726648,
  05634878,
  77888472,
  98989388
}


// pop seeds into init array
#declare K[0] = int(thrash_seed[0] / (256 * 256 * 256));
#declare K[1] = mod(int(thrash_seed[0] / (256 * 256)), 256);
#declare K[2] = mod(int(thrash_seed[0] / 256), 256);
#declare K[3] = mod(thrash_seed[0], 256);

#declare K[4] = int(thrash_seed[1] / (256 * 256 * 256));
#declare K[5] = mod(int(thrash_seed[1] / (256 * 256)), 256);
#declare K[6] = mod(int(thrash_seed[1] / 256), 256);
#declare K[7] = mod(thrash_seed[1], 256);

#declare K[8] = int(thrash_seed[2] / (256 * 256 * 256));
#declare K[9] = mod(int(thrash_seed[2] / (256 * 256)), 256);
#declare K[10] = mod(int(thrash_seed[2] / 256), 256);
#declare K[11] = mod(thrash_seed[2], 256);

#declare K[12] = int(thrash_seed[3] / (256 * 256 * 256));
#declare K[13] = mod(int(thrash_seed[3] / (256 * 256)), 256);
#declare K[14] = mod(int(thrash_seed[3] / 256), 256);
#declare K[15] = mod(thrash_seed[3], 256);


// copy/spread out the seeds into the thrasher array
#declare cc = 0;
#while (cc < (256 / 16))
  #declare K[cc + 16] = K[cc];
  #declare K[cc + 32] = K[cc];
  #declare K[cc + 48] = K[cc];
  #declare K[cc + 64] = K[cc];
  #declare K[cc + 80] = K[cc];
  #declare K[cc + 96] = K[cc];
  #declare K[cc + 112] = K[cc];
  #declare K[cc + 128] = K[cc];
  #declare K[cc + 144] = K[cc];
  #declare K[cc + 160] = K[cc];
  #declare K[cc + 176] = K[cc];
  #declare K[cc + 192] = K[cc];
  #declare K[cc + 208] = K[cc];
  #declare K[cc + 224] = K[cc];
  #declare K[cc + 240] = K[cc];
  #declare cc = cc + 1;
#end


// now initialize S array
#declare cc = 0;
#while (cc < 256)
  #declare S[cc] = cc;
  #declare cc = cc + 1;
#end


// shuffle S using K
#render "shuffle S using K ... \n"
#declare I = 0;
#while (I < 256)
  #declare J = mod((J + S[I] + K[I]), 256);
  #declare swap_temp = S[I];
  #declare S[I] = S[J];
  #declare S[J] = swap_temp;
  #declare I = I + 1;
#end


// you could toss the K array at this point since we won't use it.


#declare I = 0;
#declare J = 0;


#macro fetch_one_256() // returns integer value in range 0-255
  #declare I = mod((I + 1), 256);
  #declare J = mod((J + S[I]), 256);
  #declare swap_temp = S[I];
  #declare S[I] = S[J];
  #declare S[J] = swap_temp;
  #local T = mod((S[I] + S[J]), 256);
  S[T]
#end


#macro waste_1000() // toss the first 1000 random numbers
  // to make a better random
  #render "waste_1000 starting\n"
  #local cc = 0;
  #while (cc < 1000)
    #local dummy = fetch_one_256();
    #local cc = cc + 1;
  #end
  #render "waste_1000 finishing\n"
#end



#macro fetch_float() // same output as rand(), but no input parameter
  // first build a float value from 4 bytes
  #local ff_result = fetch_one_256() * (256 * 256 * 256) +
                     fetch_one_256() * (256 * 256) +
                     fetch_one_256() * 256 +
                     fetch_one_256();
  // second scale to 0.0 - 1.0 range
  #local ff_result = ff_result / (256 * 256 * 256 * 256);
  ff_result   // done
#end


waste_1000()


// new test the random
#declare ntsc = false;


global_settings {
  assumed_gamma 2.2
}


camera {
  location 0
  direction <0, 0, 1.5>
  #if (ntsc = true)
    right <(640 / 400) * (10/11), 0, 0>
  #else
    right <(640/480), 0, 0>
  #end
  up <0, 1, 0>
  rotate x*50
  rotate y*-20
  translate <14, 50, -34>
}


#macro rrange(rlo, rhi) // return rand float in specified range
  #local real_low = min(rlo, rhi);
  #local real_high = max(rlo, rhi);
  #local rresult = real_low + fetch_float() * (real_high - real_low);
  rresult
#end


#macro rnd_rotate()
  rotate <360 * fetch_float(), 360 * fetch_float(), 360 * fetch_float()>
#end


#macro rnd_translate()
  translate <
    4 - 8 * fetch_float(),
    4 - 8 * fetch_float(),
    4 - 8 * fetch_float()
  >
#end


#macro perturb()
  rnd_translate()
  rnd_rotate()
#end


plane { // floor
  <0, 1, 0>, 0
  pigment {
    checker
     color rgb 1,
     color rgb 0.8
    scale 8
  }
  finish { ambient 0.5 diffuse 0.5 }
  normal {
    agate
    bump_size -0.2
    perturb()
  }
}
#render "floor done\n"


#declare cc = 0;
#while (cc < 400)
  #declare xx = rrange(-7.5, 7.5);
  #declare yy = rrange(0.5, 15.5);
  #declare zz = rrange(-7.5, 7.5);
  #local orange = fetch_float();
  #local sky_blue = fetch_float();
  sphere {
    <xx, yy, zz>, 0.5
    pigment { color rgb orange * <1, 0.5, 0> + sky_blue * <0, 0.5, 1> }
    finish { ambient 0.4 diffuse 0.6 }
  }
  #declare cc = cc + 1;
#end


light_source {
  <0, 0, -3000>
  color rgb 0.5
  rotate x*34
  rotate y*41
}


light_source {
  <0, 0, -3000>
  color rgb 0.5
  rotate x*90
}


/* actual end of this file */


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.