POV-Ray : Newsgroups : povray.beta-test : rand.inc VRand_In_Sphere flaw : rand.inc VRand_In_Sphere flaw Server Time
30 Jul 2024 18:18:50 EDT (-0400)
  rand.inc VRand_In_Sphere flaw  
From: Slime
Date: 11 Oct 2001 21:29:52
Message: <3bc64790$1@news.povray.org>
Out of curiosity, I looked at rand.inc, and noticed a flaw in the way the
VRand_In_Sphere macro works. It is supposed to return random values inside a
sphere, but it has a bias that most often returns values closer to the
center of the sphere. I have solved the problem in the below code, it merely
involves taking the cube root of the radius (magnitude) of the vector to be
returned.

The following scene demonstrates the problem and solution. I'll post a
rendered version in p.b-t.b in a minute or two.

global_settings {max_trace_level 10000}

camera {
 location <0,0,-6>
 look_at 0
}

light_source {
 10000
 rgb 1
}


// define vars

#include "rand.inc"

#declare smallspheremediadensity = .15;
#declare smallsphereradius = .03;
#declare numobjects = 5000;

// place many small spheres with current VRand_In_Sphere function

#declare theobj = sphere {-x*2.2,smallsphereradius pigment {rgbt 1} interior
{media {emission smallspheremediadensity}} hollow}
#declare objnum = 0;
#declare stream = seed(453);
merge {
 #while (objnum < numobjects)
  object {theobj translate VRand_In_Sphere(stream)}
  #declare objnum = objnum + 1;
 #end
}

// place a regular sphere

sphere {0,1 pigment{rgbt 1} interior {media{emission .2}} hollow}

/* the following is my proposed fix for the VRand_In_Sphere function. */
#macro Safe_VRand_In_Sphere(Stream)
 #local Theta = 2*pi*rand(Stream);   /* this is correct, it's not too hard
to figure out */
 #local Phi = acos(2*rand(Stream)-1);  /* this is also correct, in a way
that shows that they really know what they're doing with probability */
 //#local R = rand(Stream);     /* so why wasn't this one done right? it
should use the same logic the previous one did. */
 #local R = pow(rand(Stream),1/3);   /* this fixes it. it uses the correct
logic. */
 (R*<cos(Theta)*sin(Phi),
     sin(Theta)*sin(Phi),
     cos(Phi)>)
#end

// place many small spheres with proposed Safe_VRand_In_Sphere function

#declare thegoodobj = sphere {x*2.2,smallsphereradius pigment {rgbt 1}
interior {media {emission smallspheremediadensity}} hollow}
#declare objnum = 0;
#declare stream = seed(453);
merge {
 #while (objnum < numobjects)
  object {thegoodobj translate Safe_VRand_In_Sphere(stream)}
  #declare objnum = objnum + 1;
 #end
}

/* text descriptions; unimportant */
union {
 text {
  ttf "Arial.ttf"
  "old function"
  .001,0
  scale .3
  translate -3.5*x
 }
 text {
  ttf "Arial.ttf"
  "regular sphere"
  .001,0
  scale .3
  translate-1*x
 }
 text {
  ttf "Arial.ttf"
  "proposed function"
  .001,0
  scale .3
  translate 1.5*x
 }
 translate y*2
 pigment {rgb <1,.8,.8>}
 finish {ambient 1}
}

- Slime
[ http://www.slimeland.com/ ]
[ http://www.slimeland.com/images/ ]


Post a reply to this message

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