//This solution is for equiangular (spherical) projection of stencil.
//Let`s imagine point-to-square projector, H=1 meter — distance to center of stencil.
//a — is a first total angle of lightsource,
//b — is the second angle, so we will have rectangular projector
//X,Y — linear size of total stencil
//x,y — linear size of one pixel on stencil
//picdim — size of side of picture in pixels. Square, so the same for both
//h — distance from Light Source to center of pixel. h=H/cos(a/2)
//bitmap is 1 bit, so 1=white, true,transparent for light, and 0=black
//if bitmap is 8bit, value will go as portions 1/255
X=sin(a/2)*H/cos(a/2); //check it twice, I dont like trigonometry. Look for scheme.
Y=sin(b/2)*H/cos(b/2);
x=X/picdimX;
y=Y/picdimY;
Xas=a/picdimX; //Xas — singular beam angle width (that shoots or not shoots through pixel)
Yas=a/picdimY; //Yas — singular beam width for Y dimention of stencil
//So single square beam have angle
as=2*arcsin(x/2h);
//Q = total energy of projector, based on it`s power relatively common power of all photon emitters.
//P — number of photons
//eP — energy of 1 photon
eP=Q/P;
//T=count of white pixels
//For semitransparent version T= count of subportions, 1/255 each
T=0;
define Array blacklist[0,0];
for(j=1;j<=picdimY;j++)
{
for(i=1;i<=picdimX;i++)
{
if(pixel[i,j]){ T++;}
//semitransparent version:
//if(transparency[i,j]>0){T=T+transparency[i,j]} //where transparency is from 1 to 255 (0 is excluded before)
else{blacklist[i,j]=1;} //will not deal with this pixel later
}
}
if(T==0) say bye-bye, off the projector and break;
qP=P/T; //qP — quantity of photons for 1 pixel
//for semitransparent version qP means quantity of photons for 1/255 of transparency, and will be multiplied for pixel.
//it would be cool to break image to SquareTree, to exclude totally black areas, but not now. We need simple start.
//corners of square projector have azimuths from [0,0 ] to [a, a] for X and Y rotations. Euler`s angle space is ok, i think. And projector`s normal is [a/2,a/2]
//I think it is easy to shift angles from [-a/2,-a/2][a/2,a/2] to [0,0][a,a]
//Pixels of stencil have coordinates from [0 , 0] to [picdimX, picdimY] in 2D
//direction is Euler XY vector
//________________________all previous data is static and precalculated before shooting____________________________________________________
//azimuths of sides of pixels. Rays will be shooted between em into the pixel
xAz_min=0;
xAz_max=Xas; //not necessary
yAz_min=0;
yAz_max=Yas; //not necessary
//Let'shoot!
for(j=1;j<=picdimY;j++)//all Y
{
for(i=1;i<=picdimX;i++)//all X, usually bitmaps are written as strings, so X counts first
{
if(!blacklist[i,j]){
for(k=1;k<=qP;k++) //shooting q rays for 1 pixel
//for(k=1;k<=qP*transparency[i,j];k++) //SemiTransparent version
{
Direction=[rand(from xAz_min to xAz_max) , rand(from yAz_min to yAz_max)];
//more optimized code
//Direction=[rand(from xAz_m to xAz_m+Xas) , rand(from yAz_m to yAz_m+Yas)];
Shoot(Direction);
}
//code looks like this just for understanding.
xAz_min = xAz_min+Xas;
yAz_min = yAz_min+Yas;
xAz_max = xAz_min+Xas;
xAz_max = yAz_min+Yas;
//more optimized version
//xAz_m+=Xas;
//yAz_m+=Yas;
}
else{
«Please Don`t shoot!» //just for fun.
}
}
}