|  |  | This morning I woke up with a solution
to placing a random distribution of points
onto arbitrary objects. I'm not sure if any
of you have ever had one of these dreaming
moments of inspiration, but I figured it was
worth sharing it. I think someone had asked
about something like this, but I've lost the
thread.
Basically, you just check that the distance
from a random point in the bounding to
a trace hit on the object is shorter than
some threshold distance. That way the
random distribution approaches that of
the surface.
Here's a sample scene, with the macro.
#macro RandOnSurface(Obj, rsd, thresh)
   #local mn = min_extent(Obj);
   #local mx = max_extent(Obj);
   #local dist = 1000000;
   #while (dist>thresh)
      #local flag = 0;
      #while (flag = 0)
         #local rfrom = VRand_In_Box(mn, mx, rsd);
         #local rdir = vrotate(<1,0,0>,
            <360*rand(rsd),360*rand(rsd),360*rand(rsd)>);
         #declare Norm = <0, 0, 0>;
         #local hit = trace(Obj, rfrom, rdir, Norm);
         #if (vlength(Norm) != 0)
            #local flag = 1;
         #end
      #end
      #local dist = vlength( hit - rfrom);
   #end
   #local result = hit;
   (result)
#end
#declare Bent = merge {
   cylinder{<0,-1,0>,<-1,0,0>,0.2}
   cylinder{<-1,0,0>,<1,0,0>,0.2}
   cylinder{<1,0,0>,<0,1,0>,0.2}
   sphere {<-1,0,0>,0.2}
   sphere {<1,0,0>,0.2}
};
object {Bent pigment {Blue transmit 0.7} }
#declare rsd = seed(1);
#local c = 0;
#while (c<1000)
   #local p = RandOnSurface(Bent, rsd, 0.05);
   cone{<0,0,0>,0.025,<0,0.1,0>,0
     Point_At_Trans(Norm)
     translate p
     pigment{Red}
   }
   #local c = c + 1;
#end
Post a reply to this message
 |  | 
|  |  | > brute force but should be a reasonable approximation if you
> are willing to wait a bit for all those missing rolls.
>
> Although I think you should also pick a uniform distribution
> of trace directions, otherwise you will have some unnecessary
> systematic error. But this can be fixed by
>
> http://mathworld.wolfram.com/SpherePointPicking.html
I didn't rotate 360 y and 180 relative as in polar notation,
which is what causes that common error pointed out on wolfram,
but by 360 on 3 fixed axes. The result should be uniform already?
I guess you could use Ingo's VRand_On_Sphere() from rand.inc
#local rdir = VRand_On_Sphere(rsd);
> Also, the bounding box should be extended by "threshold",
> else areas at the border only have 50% chance of hitting.
Oops, yep.
   #local mn = min_extent(Obj)-thresh;
   #local mx = max_extent(Obj)+thresh;
 Post a reply to this message
 |  | 
|  |  | > I have been playing with your macro and I have the following question, as 
> I am at a loss about how to solve it myself (see the image in p.b.i.).
>
> I scaled here the cones to a flat shape. What I would like is to always 
> have the eliptic bases oriented horizontally, whatever their location, not 
> like in the image, where part of them are oriented vertically. How could 
> that be achieved with your macro? I experimented a bit and read the docs, 
> but I am at a loss.
Trace and the RandOnSurface macro only return a point and a normal.
You could ignore the vertical portion of the normal and force some
object to be horizontal in respect to the horizon.
Point_At_Trans(vnormalize(<Norm.x,0,Norm.z>))
but you would need to decide what to do if the normal is vertical
or it might error out.
However, I think what you intend is to follow the shape of the object?
A normal isn't enough to generate info about how the surface
shape slopes nearby to some random point. You could trace nearby
points and rotate based on that perhaps.
 Post a reply to this message
 |  |