source: Dev/branches/rest-dojo-ui/client/dojox/gfx3d/lighting.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 9.0 KB
Line 
1define([
2        "dojo/_base/lang",
3        "dojo/_base/Color",     // dojo.Color
4        "dojo/_base/declare",   // dojo.declare
5        "dojox/gfx/_base",
6        "./_base"
7],function(lang,Color,declare,gfx,gfx3d) {
8
9        var lite = gfx3d.lighting = {
10                // color utilities
11                black: function(){
12                        return {r: 0, g: 0, b: 0, a: 1};
13                },
14                white: function(){
15                        return {r: 1, g: 1, b: 1, a: 1};
16                },
17                toStdColor: function(c){
18                        c = gfx.normalizeColor(c);
19                        return {r: c.r / 255, g: c.g / 255, b: c.b / 255, a: c.a};
20                },
21                fromStdColor: function(c){
22                        return new Color([Math.round(255 * c.r), Math.round(255 * c.g), Math.round(255 * c.b), c.a]);
23                },
24                scaleColor: function(s, c){
25                        return {r: s * c.r, g: s * c.g, b: s * c.b, a: s * c.a};
26                },
27                addColor: function(a, b){
28                        return {r: a.r + b.r, g: a.g + b.g, b: a.b + b.b, a: a.a + b.a};
29                },
30                multiplyColor: function(a, b){
31                        return {r: a.r * b.r, g: a.g * b.g, b: a.b * b.b, a: a.a * b.a};
32                },
33                saturateColor: function(c){
34                        return {
35                                r: c.r < 0 ? 0 : c.r > 1 ? 1 : c.r,
36                                g: c.g < 0 ? 0 : c.g > 1 ? 1 : c.g,
37                                b: c.b < 0 ? 0 : c.b > 1 ? 1 : c.b,
38                                a: c.a < 0 ? 0 : c.a > 1 ? 1 : c.a
39                        };
40                },
41                mixColor: function(c1, c2, s){
42                        return lite.addColor(lite.scaleColor(s, c1), lite.scaleColor(1 - s, c2));
43                },
44                diff2Color: function(c1, c2){
45                        var r = c1.r - c2.r;
46                        var g = c1.g - c2.g;
47                        var b = c1.b - c2.b;
48                        var a = c1.a - c2.a;
49                        return r * r + g * g + b * b + a * a;
50                },
51                length2Color: function(c){
52                        return c.r * c.r + c.g * c.g + c.b * c.b + c.a * c.a;
53                },
54               
55                // vector utilities
56                //TODO: move vector utilities from this file to vector.js
57                dot: function(a, b){
58                        return a.x * b.x + a.y * b.y + a.z * b.z;
59                },
60                scale: function(s, v){
61                        return {x: s * v.x, y: s * v.y, z: s * v.z};
62                },
63                add: function(a, b){
64                        return {x: a.x + b.x, y: a.y + b.y, z: a.z + b.z};
65                },
66                saturate: function(v){
67                        return Math.min(Math.max(v, 0), 1);
68                },
69                length: function(v){
70                        return Math.sqrt(gfx3d.lighting.dot(v, v));
71                },
72                normalize: function(v){
73                        return lite.scale(1 / lite.length(v), v);
74                },
75                faceforward: function(n, i){
76                        var p = gfx3d.lighting;
77                        var s = p.dot(i, n) < 0 ? 1 : -1;
78                        return p.scale(s, n);
79                },
80                reflect: function(i, n){
81                        var p = gfx3d.lighting;
82                        return p.add(i, p.scale(-2 * p.dot(i, n), n));
83                },
84               
85                // lighting utilities
86                diffuse: function(normal, lights){
87                        var c = lite.black();
88                        for(var i = 0; i < lights.length; ++i){
89                                var l = lights[i],
90                                        d = lite.dot(lite.normalize(l.direction), normal);
91                                c = lite.addColor(c, lite.scaleColor(d, l.color));
92                        }
93                        return lite.saturateColor(c);
94                },
95                specular: function(normal, v, roughness, lights){
96                        var c = lite.black();
97                        for(var i = 0; i < lights.length; ++i){
98                                var l = lights[i],
99                                        h = lite.normalize(lite.add(lite.normalize(l.direction), v)),
100                                        s = Math.pow(Math.max(0, lite.dot(normal, h)), 1 / roughness);
101                                c = lite.addColor(c, lite.scaleColor(s, l.color));
102                        }
103                        return lite.saturateColor(c);
104                },
105                phong: function(normal, v, size, lights){
106                        normal = lite.normalize(normal);
107                        var c = lite.black();
108                        for(var i = 0; i < lights.length; ++i){
109                                var l = lights[i],
110                                        r = lite.reflect(lite.scale(-1, lite.normalize(v)), normal),
111                                        s = Math.pow(Math.max(0, lite.dot(r, lite.normalize(l.direction))), size);
112                                c = lite.addColor(c, lite.scaleColor(s, l.color));
113                        }
114                        return lite.saturateColor(c);
115                }
116        };
117
118        // this lighting model is derived from RenderMan Interface Specification Version 3.2
119
120        declare("dojox.gfx3d.lighting.Model", null, {
121                constructor: function(incident, lights, ambient, specular){
122                        this.incident = lite.normalize(incident);
123                        this.lights = [];
124                        for(var i = 0; i < lights.length; ++i){
125                                var l = lights[i];
126                                this.lights.push({direction: lite.normalize(l.direction), color: lite.toStdColor(l.color)});
127                        }
128                        this.ambient = lite.toStdColor(ambient.color ? ambient.color : "white");
129                        this.ambient = lite.scaleColor(ambient.intensity, this.ambient);
130                        this.ambient = lite.scaleColor(this.ambient.a, this.ambient);
131                        this.ambient.a = 1;
132                        this.specular = lite.toStdColor(specular ? specular : "white");
133                        this.specular = lite.scaleColor(this.specular.a, this.specular);
134                        this.specular.a = 1;
135                        this.npr_cool = {r: 0,   g: 0,   b: 0.4, a: 1};
136                        this.npr_warm = {r: 0.4, g: 0.4, b: 0.2, a: 1};
137                        this.npr_alpha = 0.2;
138                        this.npr_beta  = 0.6;
139                        this.npr_scale = 0.6;
140                },
141                constant: function(normal, finish, pigment){
142                        pigment   = lite.toStdColor(pigment);
143                        var alpha = pigment.a, color = lite.scaleColor(alpha, pigment);
144                        color.a   = alpha;
145                        return lite.fromStdColor(lite.saturateColor(color));
146                },
147                matte: function(normal, finish, pigment){
148                        if(typeof finish == "string"){ finish = lite.finish[finish]; }
149                        pigment = lite.toStdColor(pigment);
150                        normal  = lite.faceforward(lite.normalize(normal), this.incident);
151                        var ambient = lite.scaleColor(finish.Ka, this.ambient),
152                                shadow  = lite.saturate(-4 * lite.dot(normal, this.incident)),
153                                diffuse = lite.scaleColor(shadow * finish.Kd, lite.diffuse(normal, this.lights)),
154                                color   = lite.scaleColor(pigment.a, lite.multiplyColor(pigment, lite.addColor(ambient, diffuse)));
155                        color.a = pigment.a;
156                        return lite.fromStdColor(lite.saturateColor(color));
157                },
158                metal: function(normal, finish, pigment){
159                        if(typeof finish == "string"){ finish = lite.finish[finish]; }
160                        pigment = lite.toStdColor(pigment);
161                        normal  = lite.faceforward(lite.normalize(normal), this.incident);
162                        var v = lite.scale(-1, this.incident), specular, color,
163                                ambient = lite.scaleColor(finish.Ka, this.ambient),
164                                shadow  = lite.saturate(-4 * lite.dot(normal, this.incident));
165                        if("phong" in finish){
166                                specular = lite.scaleColor(shadow * finish.Ks * finish.phong, lite.phong(normal, v, finish.phong_size, this.lights));
167                        }else{
168                                specular = lite.scaleColor(shadow * finish.Ks, lite.specular(normal, v, finish.roughness, this.lights));
169                        }
170                        color = lite.scaleColor(pigment.a, lite.addColor(lite.multiplyColor(pigment, ambient), lite.multiplyColor(this.specular, specular)));
171                        color.a = pigment.a;
172                        return lite.fromStdColor(lite.saturateColor(color));
173                },
174                plastic: function(normal, finish, pigment){
175                        if(typeof finish == "string"){ finish = lite.finish[finish]; }
176                        pigment = lite.toStdColor(pigment);
177                        normal  = lite.faceforward(lite.normalize(normal), this.incident);
178                        var v = lite.scale(-1, this.incident), specular, color,
179                                ambient = lite.scaleColor(finish.Ka, this.ambient),
180                                shadow  = lite.saturate(-4 * lite.dot(normal, this.incident)),
181                                diffuse = lite.scaleColor(shadow * finish.Kd, lite.diffuse(normal, this.lights));
182                        if("phong" in finish){
183                                specular = lite.scaleColor(shadow * finish.Ks * finish.phong, lite.phong(normal, v, finish.phong_size, this.lights));
184                        }else{
185                                specular = lite.scaleColor(shadow * finish.Ks, lite.specular(normal, v, finish.roughness, this.lights));
186                        }
187                        color = lite.scaleColor(pigment.a, lite.addColor(lite.multiplyColor(pigment, lite.addColor(ambient, diffuse)), lite.multiplyColor(this.specular, specular)));
188                        color.a = pigment.a;
189                        return lite.fromStdColor(lite.saturateColor(color));
190                },
191                npr: function(normal, finish, pigment){
192                        if(typeof finish == "string"){ finish = lite.finish[finish]; }
193                        pigment = lite.toStdColor(pigment);
194                        normal  = lite.faceforward(lite.normalize(normal), this.incident);
195                        var ambient  = lite.scaleColor(finish.Ka, this.ambient),
196                                shadow   = lite.saturate(-4 * lite.dot(normal, this.incident)),
197                                diffuse  = lite.scaleColor(shadow * finish.Kd, lite.diffuse(normal, this.lights)),
198                                color = lite.scaleColor(pigment.a, lite.multiplyColor(pigment, lite.addColor(ambient, diffuse))),
199                                cool = lite.addColor(this.npr_cool, lite.scaleColor(this.npr_alpha, color)),
200                                warm = lite.addColor(this.npr_warm, lite.scaleColor(this.npr_beta,  color)),
201                                d = (1 + lite.dot(this.incident, normal)) / 2,
202                                color = lite.scaleColor(this.npr_scale, lite.addColor(color, lite.mixColor(cool, warm, d)));
203                        color.a = pigment.a;
204                        return lite.fromStdColor(lite.saturateColor(color));
205                }
206        });
207
208
209        // POV-Ray basic finishes
210       
211        gfx3d.lighting.finish = {
212       
213                // Default
214               
215                defaults: {Ka: 0.1, Kd: 0.6, Ks: 0.0, roughness: 0.05},
216               
217                dull:     {Ka: 0.1, Kd: 0.6, Ks: 0.5, roughness: 0.15},
218                shiny:    {Ka: 0.1, Kd: 0.6, Ks: 1.0, roughness: 0.001},
219                glossy:   {Ka: 0.1, Kd: 0.6, Ks: 1.0, roughness: 0.0001},
220               
221                phong_dull:   {Ka: 0.1, Kd: 0.6, Ks: 0.5, phong: 0.5, phong_size: 1},
222                phong_shiny:  {Ka: 0.1, Kd: 0.6, Ks: 1.0, phong: 1.0, phong_size: 200},
223                phong_glossy: {Ka: 0.1, Kd: 0.6, Ks: 1.0, phong: 1.0, phong_size: 300},
224       
225                luminous: {Ka: 1.0, Kd: 0.0, Ks: 0.0, roughness: 0.05},
226       
227                // Metals
228       
229                // very soft and dull
230                metalA: {Ka: 0.35, Kd: 0.3, Ks: 0.8, roughness: 1/20},
231                // fairly soft and dull
232                metalB: {Ka: 0.30, Kd: 0.4, Ks: 0.7, roughness: 1/60},
233                // medium reflectivity, holds color well
234                metalC: {Ka: 0.25, Kd: 0.5, Ks: 0.8, roughness: 1/80},
235                // highly hard and polished, high reflectivity
236                metalD: {Ka: 0.15, Kd: 0.6, Ks: 0.8, roughness: 1/100},
237                // very highly polished and reflective
238                metalE: {Ka: 0.10, Kd: 0.7, Ks: 0.8, roughness: 1/120}
239        };
240
241        return lite;
242});
Note: See TracBrowser for help on using the repository browser.