diff options
Diffstat (limited to 'Build/source/utils/asymptote/base/three_light.asy')
-rw-r--r-- | Build/source/utils/asymptote/base/three_light.asy | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/base/three_light.asy b/Build/source/utils/asymptote/base/three_light.asy new file mode 100644 index 00000000000..388c344895a --- /dev/null +++ b/Build/source/utils/asymptote/base/three_light.asy @@ -0,0 +1,167 @@ +struct material { + pen[] p; // diffusepen,ambientpen,emissivepen,specularpen + real opacity; + real shininess; + real granularity; + void operator init(pen diffusepen=black, pen ambientpen=black, + pen emissivepen=black, pen specularpen=mediumgray, + real opacity=opacity(diffusepen), + real shininess=defaultshininess, + real granularity=-1) { + p=new pen[] {diffusepen,ambientpen,emissivepen,specularpen}; + this.opacity=opacity; + this.shininess=shininess; + this.granularity=granularity; + } + void operator init(material m, real granularity=m.granularity) { + p=copy(m.p); + opacity=m.opacity; + shininess=m.shininess; + this.granularity=granularity; + } + pen diffuse() {return p[0];} + pen ambient() {return p[1];} + pen emissive() {return p[2];} + pen specular() {return p[3];} + void diffuse(pen q) {p[0]=q;} + void ambient(pen q) {p[1]=q;} + void emissive(pen q) {p[2]=q;} + void specular(pen q) {p[3]=q;} +} + +void write(file file, string s="", material x, suffix suffix=none) +{ + write(file,s); + write(file,"{"); + write(file,"diffuse=",x.diffuse()); + write(file,", ambient=",x.ambient()); + write(file,", emissive=",x.emissive()); + write(file,", specular=",x.specular()); + write(file,", opacity=",x.opacity); + write(file,", shininess=",x.shininess); + write(file,", granularity=",x.granularity); + write(file,"}",suffix); +} + +void write(string s="", material x, suffix suffix=endl) +{ + write(stdout,s,x,suffix); +} + +bool operator == (material m, material n) +{ + return all(m.p == n.p) && m.opacity == n.opacity && + m.shininess == n.shininess && m.granularity == n.granularity; +} + +material operator cast(pen p) +{ + return material(p); +} + +material[] operator cast(pen[] p) +{ + return sequence(new material(int i) {return p[i];},p.length); +} + +pen operator ecast(material m) +{ + return m.p.length > 0 ? m.diffuse() : nullpen; +} + +material emissive(material m, real granularity=m.granularity) +{ + return material(black+opacity(m.opacity),black,m.diffuse(),black,m.opacity,1, + granularity); +} + +struct light { + real[][] diffuse; + real[][] ambient; + real[][] specular; + real specularfactor; + bool viewport; // Are the lights specified (and fixed) in the viewport frame? + triple[] position; // Only directional lights are implemented. + + transform3 T=identity(4); // Transform to apply to normal vectors. + + bool on() {return position.length > 0;} + + void operator init(pen[] diffuse=array(position.length,white), + pen[] ambient=array(position.length,black), + pen[] specular=diffuse, real specularfactor=1, + bool viewport=true, triple[] position) { + this.position=new triple[position.length]; + this.diffuse=new real[position.length][]; + this.ambient=new real[position.length][]; + this.specular=new real[position.length][]; + for(int i=0; i < position.length; ++i) { + this.position[i]=unit(position[i]); + this.diffuse[i]=rgba(diffuse[i]); + this.ambient[i]=rgba(ambient[i]); + this.specular[i]=rgba(specular[i]); + } + this.specularfactor=specularfactor; + this.viewport=viewport; + } + + void operator init(pen diffuse=white, pen ambient=black, pen specular=diffuse, + real specularfactor=1, + bool viewport=true...triple[] position) { + int n=position.length; + operator init(array(n,diffuse),array(n,ambient),array(n,specular), + specularfactor,viewport,position); + } + + void operator init(pen diffuse=white, pen ambient=black, pen specular=diffuse, + bool viewport=true, real x, real y, real z) { + operator init(diffuse,ambient,specular,viewport,(x,y,z)); + } + + void operator init(explicit light light) { + diffuse=copy(light.diffuse); + ambient=copy(light.ambient); + specular=copy(light.specular); + specularfactor=light.specularfactor; + viewport=light.viewport; + position=copy(light.position); + } + + pen color(triple normal, material m, transform3 T=T) { + if(invisible((pen) m)) return invisible; + if(position.length == 0) return m.diffuse(); + normal=unit(T*normal); + if(settings.twosided) normal *= sgn(normal.z); + real s=m.shininess*128; + real[] Diffuse=rgba(m.diffuse()); + real[] Ambient=rgba(m.ambient()); + real[] Specular=rgba(m.specular()); + real[] p=rgba(m.emissive()); + for(int i=0; i < position.length; ++i) { + triple L=viewport ? position[i] : T*position[i]; + real Ldotn=max(dot(normal,L),0); + p += ambient[i]*Ambient+Ldotn*diffuse[i]*Diffuse; +// Apply specularfactor to partially compensate non-pixel-based rendering. + if(Ldotn > 0) // Phong-Blinn model of specular reflection + p += dot(normal,unit(L+Z))^s*specularfactor*specular[i]*Specular; + } + return rgb(p[0],p[1],p[2])+opacity(opacity(m.diffuse())); + } +} + +light operator * (transform3 t, light light) +{ + light light=light(light); + if(!light.viewport) light.position=shiftless(t)*light.position; + return light; +} + +light operator cast(triple v) {return light(v);} + +light currentlight=light(ambient=rgb(0.1,0.1,0.1),specularfactor=3, + (0.25,-0.25,1)); + +light adobe=light(gray(0.4),specularfactor=3,viewport=false, + (0.5,-0.5,-0.25),(0.5,0.5,0.25), + (0.5,-0.5,0.2),(-0.5,0.5,-0.2)); +light nolight; |