POV-Ray : Newsgroups : povray.text.scene-files : Calculating Highlights on a Sphere Server Time
22 Dec 2024 23:04:37 EST (-0500)
  Calculating Highlights on a Sphere (Message 1 to 1 of 1)  
From: Micha Riser
Subject: Calculating Highlights on a Sphere
Date: 21 Mar 2002 13:33:19
Message: <3c9a2763@news.povray.org>
See thread 'Specular Lens Flares?' in p.general.


// Highlights on a Sphere
// written by Micha Riser, 2002

#macro evaluate(coef,pos)
        
        // evaluate 4th-order polynom with coefficients coef at place pos
        #local res=coef[0];
        #local n=1;
        #local pospow=pos;
        #while(n<5)
                #local res=res+coef[n]*pospow;
                #local n=n+1;
                #local pospow=pospow*pos;       
        #end
        
        res

#end

#macro calc_n(l,a,px,py)

        // calculate the vector poiting from origin to the point of highlight

        #if ((abs(l-1)<0.00001)|(l<0)) 
                // if (l<0) there is no reasonable solution
                // if l==1 solution is simple and could be calculated
                #debug "failure in calculation\n" <0,0,0> 
        #else

                #local factor=(l-1)/(a*a*l*l-px*px-py*py);
                factor*<a*l+px,py,0>
        #end

#end


// macro to calculate position of highlight on a sphere
// camera: position <a,0,0>
// light_source: position <px,py,0>
// sphere: position <0,0,0>, radius 1

#macro highlight(a,px,py)

        #local p=array[5]   // holding coefficients of polynom
        #local dp=array[5]  // holding coefficients of derivation of p

        // calculate coefficients of polynom
        #local p_length=pow(px,2)+pow(py,2);

        #local p[0]=pow(px,4)+pow(py,4)+2*px*px*py*py-p_length;
        #local p[1]=2*(p_length-a*px);
        #local p[2]=4*a*px-a*a-p_length*(1+2*a*a);
        #local p[3]=2*a*(a-px);
        #local p[4]=a*a*(a*a-1);

        // derivate polynom
        #local dp[0]=p[1];
        #local dp[1]=2*p[2];
        #local dp[2]=3*p[3];
        #local dp[3]=4*p[4];
        #local dp[4]=0;

        // if both light source and camera is outside the sphere 
        // there has to be lmin <= l <= lmax
        #local lmin=(sqrt(p_length)-1)/(abs(a)+1);
        #local lmax=(sqrt(p_length)+1)/(abs(a)-1);
        
        // use some very quick'n dirty newton algorithm to calculate
        // roots of the polynom (uses lmin and lmax as starting points).
        // needs to be reimplemented to find all four roots
        #local i=0;
        #local sol=lmin;
        #while(i<20)
                
                #local sol=sol-(evaluate(p,sol)/evaluate(dp,sol));
                #debug str(sol,3,10)
                #debug "\n"     
                #local i=i+1;
        
        #end    
        #declare sol1=sol;

        #local i=0;
        #local sol=lmax;        
        #while(i<20)    
                
                #local sol=sol-(evaluate(p,sol)/evaluate(dp,sol));
                #debug str(sol,3,10)
                #debug "\n"     
                #local i=i+1;
        
        #end
        #declare sol2=sol;
        
        // place sphere at the calculated position to mark the center
        // of the highlight (one should place the lens flare there instead)
        
        sphere{calc_n(sol1,a,px,py),0.05 pigment{rgb <1,0,0>} finish{ambient 0.8} 
no_shadow}
        sphere{calc_n(sol2,a,px,py),0.05 pigment{rgb <1,0,0>} finish{ambient 0.8} 
no_shadow}
        


        camera{
                location <a,0,0>
                look_at 0
                }
        light_source {
                <px,py,0>
                color 1
                }


#end

/////////////////////////////////////////////////////////////////

// Test scene

#declare animation=3; // choses among there different animations
#declare Transmit=0;  // sphere's transmit value
                      // transmit allows to see hidden highlights

#if (animation=1)
        // animate camera
        #declare a_anim=10-clock*9;
        #declare px_anim=0;
        #declare py_anim=4;     
#end

#if (animation=2)
        // animate lightsource from -x to +x
        #declare a_anim=4;
        #declare px_anim=-6+clock*15;
        #declare py_anim=4;     
#end

#if (animation=3)
        // animate lightsource from -y to +y
        #declare a_anim=4;
        #declare px_anim=1.5;
        #declare py_anim=-5+clock*10;   
#end    
        
highlight(a_anim,px_anim,py_anim)

sphere{0,1 pigment{rgb 1 transmit Transmit} finish{specular 1 roughness 
.01}}


Post a reply to this message

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