e3838cfb6148b8ac6754cbcfaa9e0902b0defd67.svn-base 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. if (!dojo._hasResource["dojox.gfx3d.lighting"]) { // _hasResource checks added
  2. // by build. Do not use
  3. // _hasResource directly in
  4. // your code.
  5. dojo._hasResource["dojox.gfx3d.lighting"] = true;
  6. dojo.provide("dojox.gfx3d.lighting");
  7. dojo.require("dojox.gfx._base");
  8. (function() {
  9. var lite = dojox.gfx3d.lighting;
  10. dojo.mixin(dojox.gfx3d.lighting, {
  11. // color utilities
  12. black : function() {
  13. return {
  14. r : 0,
  15. g : 0,
  16. b : 0,
  17. a : 1
  18. };
  19. },
  20. white : function() {
  21. return {
  22. r : 1,
  23. g : 1,
  24. b : 1,
  25. a : 1
  26. };
  27. },
  28. toStdColor : function(c) {
  29. c = dojox.gfx.normalizeColor(c);
  30. return {
  31. r : c.r / 255,
  32. g : c.g / 255,
  33. b : c.b / 255,
  34. a : c.a
  35. };
  36. },
  37. fromStdColor : function(c) {
  38. return new dojo.Color([Math.round(255 * c.r),
  39. Math.round(255 * c.g), Math.round(255 * c.b), c.a]);
  40. },
  41. scaleColor : function(s, c) {
  42. return {
  43. r : s * c.r,
  44. g : s * c.g,
  45. b : s * c.b,
  46. a : s * c.a
  47. };
  48. },
  49. addColor : function(a, b) {
  50. return {
  51. r : a.r + b.r,
  52. g : a.g + b.g,
  53. b : a.b + b.b,
  54. a : a.a + b.a
  55. };
  56. },
  57. multiplyColor : function(a, b) {
  58. return {
  59. r : a.r * b.r,
  60. g : a.g * b.g,
  61. b : a.b * b.b,
  62. a : a.a * b.a
  63. };
  64. },
  65. saturateColor : function(c) {
  66. return {
  67. r : c.r < 0 ? 0 : c.r > 1 ? 1 : c.r,
  68. g : c.g < 0 ? 0 : c.g > 1 ? 1 : c.g,
  69. b : c.b < 0 ? 0 : c.b > 1 ? 1 : c.b,
  70. a : c.a < 0 ? 0 : c.a > 1 ? 1 : c.a
  71. };
  72. },
  73. mixColor : function(c1, c2, s) {
  74. return lite.addColor(lite.scaleColor(s, c1), lite.scaleColor(1
  75. - s, c2));
  76. },
  77. diff2Color : function(c1, c2) {
  78. var r = c1.r - c2.r;
  79. var g = c1.g - c2.g;
  80. var b = c1.b - c2.b;
  81. var a = c1.a - c2.a;
  82. return r * r + g * g + b * b + a * a;
  83. },
  84. length2Color : function(c) {
  85. return c.r * c.r + c.g * c.g + c.b * c.b + c.a * c.a;
  86. },
  87. // vector utilities
  88. // TODO: move vector utilities from this file to vector.js
  89. dot : function(a, b) {
  90. return a.x * b.x + a.y * b.y + a.z * b.z;
  91. },
  92. scale : function(s, v) {
  93. return {
  94. x : s * v.x,
  95. y : s * v.y,
  96. z : s * v.z
  97. };
  98. },
  99. add : function(a, b) {
  100. return {
  101. x : a.x + b.x,
  102. y : a.y + b.y,
  103. z : a.z + b.z
  104. };
  105. },
  106. saturate : function(v) {
  107. return Math.min(Math.max(v, 0), 1);
  108. },
  109. length : function(v) {
  110. return Math.sqrt(dojox.gfx3d.lighting.dot(v, v));
  111. },
  112. normalize : function(v) {
  113. return lite.scale(1 / lite.length(v), v);
  114. },
  115. faceforward : function(n, i) {
  116. var p = dojox.gfx3d.lighting;
  117. var s = p.dot(i, n) < 0 ? 1 : -1;
  118. return p.scale(s, n);
  119. },
  120. reflect : function(i, n) {
  121. var p = dojox.gfx3d.lighting;
  122. return p.add(i, p.scale(-2 * p.dot(i, n), n));
  123. },
  124. // lighting utilities
  125. diffuse : function(normal, lights) {
  126. var c = lite.black();
  127. for (var i = 0; i < lights.length; ++i) {
  128. var l = lights[i], d = lite.dot(
  129. lite.normalize(l.direction), normal);
  130. c = lite.addColor(c, lite.scaleColor(d, l.color));
  131. }
  132. return lite.saturateColor(c);
  133. },
  134. specular : function(normal, v, roughness, lights) {
  135. var c = lite.black();
  136. for (var i = 0; i < lights.length; ++i) {
  137. var l = lights[i], h = lite.normalize(lite.add(lite
  138. .normalize(l.direction), v)), s = Math.pow(
  139. Math.max(0, lite.dot(normal, h)), 1 / roughness);
  140. c = lite.addColor(c, lite.scaleColor(s, l.color));
  141. }
  142. return lite.saturateColor(c);
  143. },
  144. phong : function(normal, v, size, lights) {
  145. normal = lite.normalize(normal);
  146. var c = lite.black();
  147. for (var i = 0; i < lights.length; ++i) {
  148. var l = lights[i], r = lite.reflect(lite.scale(-1, lite
  149. .normalize(v)), normal), s = Math
  150. .pow(
  151. Math
  152. .max(
  153. 0,
  154. lite
  155. .dot(
  156. r,
  157. lite
  158. .normalize(l.direction))),
  159. size);
  160. c = lite.addColor(c, lite.scaleColor(s, l.color));
  161. }
  162. return lite.saturateColor(c);
  163. }
  164. });
  165. // this lighting model is derived from RenderMan Interface Specification
  166. // Version 3.2
  167. dojo.declare("dojox.gfx3d.lighting.Model", null, {
  168. constructor : function(incident, lights, ambient, specular) {
  169. this.incident = lite.normalize(incident);
  170. this.lights = [];
  171. for (var i = 0; i < lights.length; ++i) {
  172. var l = lights[i];
  173. this.lights.push({
  174. direction : lite.normalize(l.direction),
  175. color : lite.toStdColor(l.color)
  176. });
  177. }
  178. this.ambient = lite.toStdColor(ambient.color
  179. ? ambient.color
  180. : "white");
  181. this.ambient = lite.scaleColor(ambient.intensity, this.ambient);
  182. this.ambient = lite.scaleColor(this.ambient.a, this.ambient);
  183. this.ambient.a = 1;
  184. this.specular = lite.toStdColor(specular ? specular : "white");
  185. this.specular = lite.scaleColor(this.specular.a, this.specular);
  186. this.specular.a = 1;
  187. this.npr_cool = {
  188. r : 0,
  189. g : 0,
  190. b : 0.4,
  191. a : 1
  192. };
  193. this.npr_warm = {
  194. r : 0.4,
  195. g : 0.4,
  196. b : 0.2,
  197. a : 1
  198. };
  199. this.npr_alpha = 0.2;
  200. this.npr_beta = 0.6;
  201. this.npr_scale = 0.6;
  202. },
  203. constant : function(normal, finish, pigment) {
  204. pigment = lite.toStdColor(pigment);
  205. var alpha = pigment.a, color = lite.scaleColor(alpha, pigment);
  206. color.a = alpha;
  207. return lite.fromStdColor(lite.saturateColor(color));
  208. },
  209. matte : function(normal, finish, pigment) {
  210. if (typeof finish == "string") {
  211. finish = lite.finish[finish];
  212. }
  213. pigment = lite.toStdColor(pigment);
  214. normal = lite
  215. .faceforward(lite.normalize(normal), this.incident);
  216. var ambient = lite.scaleColor(finish.Ka, this.ambient), shadow = lite
  217. .saturate(-4 * lite.dot(normal, this.incident)), diffuse = lite
  218. .scaleColor(shadow * finish.Kd, lite.diffuse(normal,
  219. this.lights)), color = lite.scaleColor(
  220. pigment.a, lite.multiplyColor(pigment, lite.addColor(
  221. ambient, diffuse)));
  222. color.a = pigment.a;
  223. return lite.fromStdColor(lite.saturateColor(color));
  224. },
  225. metal : function(normal, finish, pigment) {
  226. if (typeof finish == "string") {
  227. finish = lite.finish[finish];
  228. }
  229. pigment = lite.toStdColor(pigment);
  230. normal = lite
  231. .faceforward(lite.normalize(normal), this.incident);
  232. var v = lite.scale(-1, this.incident), specular, color, ambient = lite
  233. .scaleColor(finish.Ka, this.ambient), shadow = lite
  234. .saturate(-4 * lite.dot(normal, this.incident));
  235. if ("phong" in finish) {
  236. specular = lite.scaleColor(shadow * finish.Ks
  237. * finish.phong, lite.phong(normal, v,
  238. finish.phong_size, this.lights));
  239. } else {
  240. specular = lite.scaleColor(shadow * finish.Ks, lite
  241. .specular(normal, v, finish.roughness,
  242. this.lights));
  243. }
  244. color = lite.scaleColor(pigment.a, lite
  245. .addColor(lite.multiplyColor(pigment, ambient),
  246. lite.multiplyColor(this.specular,
  247. specular)));
  248. color.a = pigment.a;
  249. return lite.fromStdColor(lite.saturateColor(color));
  250. },
  251. plastic : function(normal, finish, pigment) {
  252. if (typeof finish == "string") {
  253. finish = lite.finish[finish];
  254. }
  255. pigment = lite.toStdColor(pigment);
  256. normal = lite
  257. .faceforward(lite.normalize(normal), this.incident);
  258. var v = lite.scale(-1, this.incident), specular, color, ambient = lite
  259. .scaleColor(finish.Ka, this.ambient), shadow = lite
  260. .saturate(-4 * lite.dot(normal, this.incident)), diffuse = lite
  261. .scaleColor(shadow * finish.Kd, lite.diffuse(normal,
  262. this.lights));
  263. if ("phong" in finish) {
  264. specular = lite.scaleColor(shadow * finish.Ks
  265. * finish.phong, lite.phong(normal, v,
  266. finish.phong_size, this.lights));
  267. } else {
  268. specular = lite.scaleColor(shadow * finish.Ks, lite
  269. .specular(normal, v, finish.roughness,
  270. this.lights));
  271. }
  272. color = lite.scaleColor(pigment.a, lite.addColor(lite
  273. .multiplyColor(pigment, lite.addColor(
  274. ambient, diffuse)),
  275. lite.multiplyColor(this.specular, specular)));
  276. color.a = pigment.a;
  277. return lite.fromStdColor(lite.saturateColor(color));
  278. },
  279. npr : function(normal, finish, pigment) {
  280. if (typeof finish == "string") {
  281. finish = lite.finish[finish];
  282. }
  283. pigment = lite.toStdColor(pigment);
  284. normal = lite
  285. .faceforward(lite.normalize(normal), this.incident);
  286. var ambient = lite.scaleColor(finish.Ka, this.ambient), shadow = lite
  287. .saturate(-4 * lite.dot(normal, this.incident)), diffuse = lite
  288. .scaleColor(shadow * finish.Kd, lite.diffuse(normal,
  289. this.lights)), color = lite.scaleColor(
  290. pigment.a, lite.multiplyColor(pigment, lite.addColor(
  291. ambient, diffuse))), cool = lite
  292. .addColor(this.npr_cool, lite.scaleColor(
  293. this.npr_alpha, color)), warm = lite
  294. .addColor(this.npr_warm, lite.scaleColor(this.npr_beta,
  295. color)), d = (1 + lite.dot(
  296. this.incident, normal))
  297. / 2, color = lite.scaleColor(this.npr_scale, lite
  298. .addColor(color, lite.mixColor(cool, warm, d)));
  299. color.a = pigment.a;
  300. return lite.fromStdColor(lite.saturateColor(color));
  301. }
  302. });
  303. })();
  304. // POV-Ray basic finishes
  305. dojox.gfx3d.lighting.finish = {
  306. // Default
  307. defaults : {
  308. Ka : 0.1,
  309. Kd : 0.6,
  310. Ks : 0.0,
  311. roughness : 0.05
  312. },
  313. dull : {
  314. Ka : 0.1,
  315. Kd : 0.6,
  316. Ks : 0.5,
  317. roughness : 0.15
  318. },
  319. shiny : {
  320. Ka : 0.1,
  321. Kd : 0.6,
  322. Ks : 1.0,
  323. roughness : 0.001
  324. },
  325. glossy : {
  326. Ka : 0.1,
  327. Kd : 0.6,
  328. Ks : 1.0,
  329. roughness : 0.0001
  330. },
  331. phong_dull : {
  332. Ka : 0.1,
  333. Kd : 0.6,
  334. Ks : 0.5,
  335. phong : 0.5,
  336. phong_size : 1
  337. },
  338. phong_shiny : {
  339. Ka : 0.1,
  340. Kd : 0.6,
  341. Ks : 1.0,
  342. phong : 1.0,
  343. phong_size : 200
  344. },
  345. phong_glossy : {
  346. Ka : 0.1,
  347. Kd : 0.6,
  348. Ks : 1.0,
  349. phong : 1.0,
  350. phong_size : 300
  351. },
  352. luminous : {
  353. Ka : 1.0,
  354. Kd : 0.0,
  355. Ks : 0.0,
  356. roughness : 0.05
  357. },
  358. // Metals
  359. // very soft and dull
  360. metalA : {
  361. Ka : 0.35,
  362. Kd : 0.3,
  363. Ks : 0.8,
  364. roughness : 1 / 20
  365. },
  366. // fairly soft and dull
  367. metalB : {
  368. Ka : 0.30,
  369. Kd : 0.4,
  370. Ks : 0.7,
  371. roughness : 1 / 60
  372. },
  373. // medium reflectivity, holds color well
  374. metalC : {
  375. Ka : 0.25,
  376. Kd : 0.5,
  377. Ks : 0.8,
  378. roughness : 1 / 80
  379. },
  380. // highly hard and polished, high reflectivity
  381. metalD : {
  382. Ka : 0.15,
  383. Kd : 0.6,
  384. Ks : 0.8,
  385. roughness : 1 / 100
  386. },
  387. // very highly polished and reflective
  388. metalE : {
  389. Ka : 0.10,
  390. Kd : 0.7,
  391. Ks : 0.8,
  392. roughness : 1 / 120
  393. }
  394. };
  395. }