raytrace.js_c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. var performance = performance || {};
  2. performance.now = function () {
  3. return performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || Date.now
  4. }();
  5. function Benchmark(a, c, b, d, e, f, g, h, l) {
  6. this.name = a;
  7. this.doWarmup = c;
  8. this.doDeterministic = b;
  9. this.deterministicIterations = d;
  10. this.run = e;
  11. this.Setup = f ? f : function () { };
  12. this.TearDown = g ? g : function () { };
  13. this.rmsResult = h ? h : null;
  14. this.minIterations = l ? l : 32
  15. }
  16. function BenchmarkResult(a, c, b) {
  17. this.benchmark = a;
  18. this.time = c;
  19. this.latency = b
  20. }
  21. BenchmarkResult.prototype.valueOf = function () {
  22. return this.time
  23. };
  24. function BenchmarkSuite(a, c, b) {
  25. this.name = a;
  26. this.reference = c;
  27. this.benchmarks = b;
  28. BenchmarkSuite.suites.push(this)
  29. }
  30. BenchmarkSuite.suites = [];
  31. BenchmarkSuite.version = "9";
  32. BenchmarkSuite.config = {
  33. doWarmup: void 0,
  34. doDeterministic: void 0
  35. };
  36. alert = function (a) {
  37. throw "Alert called with argument: " + a;
  38. };
  39. BenchmarkSuite.ResetRNG = function () {
  40. Math.random = function () {
  41. var a = 49734321;
  42. return function () {
  43. a = a + 2127912214 + (a << 12) & 4294967295;
  44. a = (a ^ 3345072700 ^ a >>> 19) & 4294967295;
  45. a = a + 374761393 + (a << 5) & 4294967295;
  46. a = (a + 3550635116 ^ a << 9) & 4294967295;
  47. a = a + 4251993797 + (a << 3) & 4294967295;
  48. a = (a ^ 3042594569 ^ a >>> 16) & 4294967295;
  49. return (a & 268435455) / 268435456
  50. }
  51. }()
  52. };
  53. BenchmarkSuite.RunSuites = function (a, c) {
  54. function b() {
  55. for (; d || g < f;) {
  56. if (d) d = d();
  57. else {
  58. var h = e[g++];
  59. a.NotifyStart && a.NotifyStart(h.name); -1 < c.indexOf(h.name) ? h.NotifySkipped(a) : d = h.RunStep(a)
  60. }
  61. if (d && "undefined" != typeof window && window.setTimeout) {
  62. window.setTimeout(b, 25);
  63. return
  64. }
  65. }
  66. a.NotifyScore && (h = BenchmarkSuite.GeometricMean(BenchmarkSuite.scores), h = BenchmarkSuite.FormatScore(100 * h), a.NotifyScore(h))
  67. }
  68. c = "undefined" === typeof c ? [] : c;
  69. var d = null,
  70. e = BenchmarkSuite.suites,
  71. f = e.length;
  72. BenchmarkSuite.scores = [];
  73. var g =
  74. 0;
  75. b()
  76. };
  77. BenchmarkSuite.CountBenchmarks = function () {
  78. for (var a = 0, c = BenchmarkSuite.suites, b = 0; b < c.length; b++) a += c[b].benchmarks.length;
  79. return a
  80. };
  81. BenchmarkSuite.GeometricMean = function (a) {
  82. for (var c = 0, b = 0; b < a.length; b++) c += Math.log(a[b]);
  83. return Math.pow(Math.E, c / a.length)
  84. };
  85. BenchmarkSuite.GeometricMeanTime = function (a) {
  86. for (var c = 0, b = 0; b < a.length; b++) c += Math.log(a[b].time);
  87. return Math.pow(Math.E, c / a.length)
  88. };
  89. BenchmarkSuite.GeometricMeanLatency = function (a) {
  90. for (var c = 0, b = !1, d = 0; d < a.length; d++) 0 != a[d].latency && (c += Math.log(a[d].latency), b = !0);
  91. return b ? Math.pow(Math.E, c / a.length) : 0
  92. };
  93. BenchmarkSuite.FormatScore = function (a) {
  94. return 100 < a ? a.toFixed(0) : a.toPrecision(3)
  95. };
  96. BenchmarkSuite.prototype.NotifyStep = function (a) {
  97. this.results.push(a);
  98. this.runner.NotifyStep && this.runner.NotifyStep(a.benchmark.name)
  99. };
  100. BenchmarkSuite.prototype.NotifyResult = function () {
  101. var a = BenchmarkSuite.GeometricMeanTime(this.results),
  102. a = this.reference[0] / a;
  103. BenchmarkSuite.scores.push(a);
  104. this.runner.NotifyResult && (a = BenchmarkSuite.FormatScore(100 * a), this.runner.NotifyResult(this.name, a));
  105. 2 == this.reference.length && (a = BenchmarkSuite.GeometricMeanLatency(this.results), 0 != a && (a = this.reference[1] / a, BenchmarkSuite.scores.push(a), this.runner.NotifyResult && (a = BenchmarkSuite.FormatScore(100 * a), this.runner.NotifyResult(this.name + "Latency",
  106. a))))
  107. };
  108. BenchmarkSuite.prototype.NotifySkipped = function (a) {
  109. BenchmarkSuite.scores.push(1);
  110. a.NotifyResult && a.NotifyResult(this.name, "Skipped")
  111. };
  112. BenchmarkSuite.prototype.NotifyError = function (a) {
  113. this.runner.NotifyError && this.runner.NotifyError(this.name, a);
  114. this.runner.NotifyStep && this.runner.NotifyStep(this.name)
  115. };
  116. BenchmarkSuite.prototype.RunSingleBenchmark = function (a, c) {
  117. function b(b) {
  118. for (var c = 0, d = new Date, f = 0; e ? f < a.deterministicIterations : 1E3 > c; f++) a.run(), c = new Date - d;
  119. null != b && (b.runs += f, b.elapsed += c)
  120. }
  121. var d = BenchmarkSuite.config,
  122. e = void 0 !== d.doDeterministic ? d.doDeterministic : a.doDeterministic;
  123. (void 0 !== d.doWarmup ? d.doWarmup : a.doWarmup) || null != c || (c = {
  124. runs: 0,
  125. elapsed: 0
  126. });
  127. if (null == c) return b(null), {
  128. runs: 0,
  129. elapsed: 0
  130. };
  131. b(c);
  132. if (c.runs < a.minIterations) return c;
  133. var d = 1E3 * c.elapsed / c.runs,
  134. f = null != a.rmsResult ? a.rmsResult() :
  135. 0;
  136. this.NotifyStep(new BenchmarkResult(a, d, f));
  137. return null
  138. };
  139. BenchmarkSuite.prototype.RunStep = function (a) {
  140. function c() {
  141. if (f < e) {
  142. try {
  143. g.benchmarks[f].Setup()
  144. } catch (a) {
  145. return g.NotifyError(a), null
  146. }
  147. return b
  148. }
  149. g.NotifyResult();
  150. return null
  151. }
  152. function b() {
  153. try {
  154. h = g.RunSingleBenchmark(g.benchmarks[f], h)
  155. } catch (a) {
  156. return g.NotifyError(a), null
  157. }
  158. return null == h ? d : b()
  159. }
  160. function d() {
  161. try {
  162. g.benchmarks[f++].TearDown()
  163. } catch (a) {
  164. return g.NotifyError(a), null
  165. }
  166. return c
  167. }
  168. BenchmarkSuite.ResetRNG();
  169. this.results = [];
  170. this.runner = a;
  171. var e = this.benchmarks.length,
  172. f = 0,
  173. g = this,
  174. h;
  175. return c()
  176. };
  177. var RayTrace = new BenchmarkSuite("RayTrace", [739989], [new Benchmark("RayTrace", !0, !1, 600, renderScene)]),
  178. checkNumber, Class = {
  179. create: function () {
  180. return function () {
  181. this.initialize.apply(this, arguments)
  182. }
  183. }
  184. };
  185. Object.extend = function (a, c) {
  186. for (var b in c) a[b] = c[b];
  187. return a
  188. };
  189. if ("undefined" == typeof Flog) var Flog = {};
  190. "undefined" == typeof Flog.RayTracer && (Flog.RayTracer = {});
  191. Flog.RayTracer.Color = Class.create();
  192. Flog.RayTracer.Color.prototype = {
  193. red: 0,
  194. green: 0,
  195. blue: 0,
  196. initialize: function (a, c, b) {
  197. a || (a = 0);
  198. c || (c = 0);
  199. b || (b = 0);
  200. this.red = a;
  201. this.green = c;
  202. this.blue = b
  203. },
  204. add: function (a, c) {
  205. var b = new Flog.RayTracer.Color(0, 0, 0);
  206. b.red = a.red + c.red;
  207. b.green = a.green + c.green;
  208. b.blue = a.blue + c.blue;
  209. return b
  210. },
  211. addScalar: function (a, c) {
  212. var b = new Flog.RayTracer.Color(0, 0, 0);
  213. b.red = a.red + c;
  214. b.green = a.green + c;
  215. b.blue = a.blue + c;
  216. b.limit();
  217. return b
  218. },
  219. subtract: function (a, c) {
  220. var b = new Flog.RayTracer.Color(0, 0, 0);
  221. b.red = a.red - c.red;
  222. b.green = a.green - c.green;
  223. b.blue = a.blue - c.blue;
  224. return b
  225. },
  226. multiply: function (a, c) {
  227. var b = new Flog.RayTracer.Color(0, 0, 0);
  228. b.red = a.red * c.red;
  229. b.green = a.green * c.green;
  230. b.blue = a.blue * c.blue;
  231. return b
  232. },
  233. multiplyScalar: function (a, c) {
  234. var b = new Flog.RayTracer.Color(0, 0, 0);
  235. b.red = a.red * c;
  236. b.green = a.green * c;
  237. b.blue = a.blue * c;
  238. return b
  239. },
  240. divideFactor: function (a, c) {
  241. var b = new Flog.RayTracer.Color(0, 0, 0);
  242. b.red = a.red / c;
  243. b.green = a.green / c;
  244. b.blue = a.blue / c;
  245. return b
  246. },
  247. limit: function () {
  248. this.red = 0 < this.red ? 1 < this.red ? 1 : this.red : 0;
  249. this.green = 0 < this.green ? 1 < this.green ?
  250. 1 : this.green : 0;
  251. this.blue = 0 < this.blue ? 1 < this.blue ? 1 : this.blue : 0
  252. },
  253. distance: function (a) {
  254. return Math.abs(this.red - a.red) + Math.abs(this.green - a.green) + Math.abs(this.blue - a.blue)
  255. },
  256. blend: function (a, c, b) {
  257. new Flog.RayTracer.Color(0, 0, 0);
  258. return Flog.RayTracer.Color.prototype.add(Flog.RayTracer.Color.prototype.multiplyScalar(a, 1 - b), Flog.RayTracer.Color.prototype.multiplyScalar(c, b))
  259. },
  260. brightness: function () {
  261. return 77 * Math.floor(255 * this.red) + 150 * Math.floor(255 * this.green) + 29 * Math.floor(255 * this.blue) >> 8
  262. },
  263. toString: function () {
  264. return "rgb(" +
  265. Math.floor(255 * this.red) + "," + Math.floor(255 * this.green) + "," + Math.floor(255 * this.blue) + ")"
  266. }
  267. };
  268. "undefined" == typeof Flog && (Flog = {});
  269. "undefined" == typeof Flog.RayTracer && (Flog.RayTracer = {});
  270. Flog.RayTracer.Light = Class.create();
  271. Flog.RayTracer.Light.prototype = {
  272. position: null,
  273. color: null,
  274. intensity: 10,
  275. initialize: function (a, c, b) {
  276. this.position = a;
  277. this.color = c;
  278. this.intensity = b ? b : 10
  279. },
  280. toString: function () {
  281. return "Light [" + this.position.x + "," + this.position.y + "," + this.position.z + "]"
  282. }
  283. };
  284. "undefined" == typeof Flog && (Flog = {});
  285. "undefined" == typeof Flog.RayTracer && (Flog.RayTracer = {});
  286. Flog.RayTracer.Vector = Class.create();
  287. Flog.RayTracer.Vector.prototype = {
  288. x: 0,
  289. y: 0,
  290. z: 0,
  291. initialize: function (a, c, b) {
  292. this.x = a ? a : 0;
  293. this.y = c ? c : 0;
  294. this.z = b ? b : 0
  295. },
  296. copy: function (a) {
  297. this.x = a.x;
  298. this.y = a.y;
  299. this.z = a.z
  300. },
  301. normalize: function () {
  302. var a = this.magnitude();
  303. return new Flog.RayTracer.Vector(this.x / a, this.y / a, this.z / a)
  304. },
  305. magnitude: function () {
  306. return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z)
  307. },
  308. cross: function (a) {
  309. return new Flog.RayTracer.Vector(-this.z * a.y + this.y * a.z, this.z * a.x - this.x * a.z, -this.y * a.x + this.x * a.y)
  310. },
  311. dot: function (a) {
  312. return this.x *
  313. a.x + this.y * a.y + this.z * a.z
  314. },
  315. add: function (a, c) {
  316. return new Flog.RayTracer.Vector(c.x + a.x, c.y + a.y, c.z + a.z)
  317. },
  318. subtract: function (a, c) {
  319. if (!c || !a) throw "Vectors must be defined [" + a + "," + c + "]";
  320. return new Flog.RayTracer.Vector(a.x - c.x, a.y - c.y, a.z - c.z)
  321. },
  322. multiplyVector: function (a, c) {
  323. return new Flog.RayTracer.Vector(a.x * c.x, a.y * c.y, a.z * c.z)
  324. },
  325. multiplyScalar: function (a, c) {
  326. return new Flog.RayTracer.Vector(a.x * c, a.y * c, a.z * c)
  327. },
  328. toString: function () {
  329. return "Vector [" + this.x + "," + this.y + "," + this.z + "]"
  330. }
  331. };
  332. "undefined" == typeof Flog && (Flog = {});
  333. "undefined" == typeof Flog.RayTracer && (Flog.RayTracer = {});
  334. Flog.RayTracer.Ray = Class.create();
  335. Flog.RayTracer.Ray.prototype = {
  336. position: null,
  337. direction: null,
  338. initialize: function (a, c) {
  339. this.position = a;
  340. this.direction = c
  341. },
  342. toString: function () {
  343. return "Ray [" + this.position + "," + this.direction + "]"
  344. }
  345. };
  346. "undefined" == typeof Flog && (Flog = {});
  347. "undefined" == typeof Flog.RayTracer && (Flog.RayTracer = {});
  348. Flog.RayTracer.Scene = Class.create();
  349. Flog.RayTracer.Scene.prototype = {
  350. camera: null,
  351. shapes: [],
  352. lights: [],
  353. background: null,
  354. initialize: function () {
  355. this.camera = new Flog.RayTracer.Camera(new Flog.RayTracer.Vector(0, 0, -5), new Flog.RayTracer.Vector(0, 0, 1), new Flog.RayTracer.Vector(0, 1, 0));
  356. this.shapes = [];
  357. this.lights = [];
  358. this.background = new Flog.RayTracer.Background(new Flog.RayTracer.Color(0, 0, .5), .2)
  359. }
  360. };
  361. "undefined" == typeof Flog && (Flog = {});
  362. "undefined" == typeof Flog.RayTracer && (Flog.RayTracer = {});
  363. "undefined" == typeof Flog.RayTracer.Material && (Flog.RayTracer.Material = {});
  364. Flog.RayTracer.Material.BaseMaterial = Class.create();
  365. Flog.RayTracer.Material.BaseMaterial.prototype = {
  366. gloss: 2,
  367. transparency: 0,
  368. reflection: 0,
  369. refraction: .5,
  370. hasTexture: !1,
  371. initialize: function () { },
  372. getColor: function (a, c) { },
  373. wrapUp: function (a) {
  374. a %= 2; -1 > a && (a += 2);
  375. 1 <= a && (a -= 2);
  376. return a
  377. },
  378. toString: function () {
  379. return "Material [gloss=" + this.gloss + ", transparency=" + this.transparency + ", hasTexture=" + this.hasTexture + "]"
  380. }
  381. };
  382. "undefined" == typeof Flog && (Flog = {});
  383. "undefined" == typeof Flog.RayTracer && (Flog.RayTracer = {});
  384. Flog.RayTracer.Material.Solid = Class.create();
  385. Flog.RayTracer.Material.Solid.prototype = Object.extend(new Flog.RayTracer.Material.BaseMaterial, {
  386. initialize: function (a, c, b, d, e) {
  387. this.color = a;
  388. this.reflection = c;
  389. this.transparency = d;
  390. this.gloss = e;
  391. this.hasTexture = !1
  392. },
  393. getColor: function (a, c) {
  394. return this.color
  395. },
  396. toString: function () {
  397. return "SolidMaterial [gloss=" + this.gloss + ", transparency=" + this.transparency + ", hasTexture=" + this.hasTexture + "]"
  398. }
  399. });
  400. "undefined" == typeof Flog && (Flog = {});
  401. "undefined" == typeof Flog.RayTracer && (Flog.RayTracer = {});
  402. Flog.RayTracer.Material.Chessboard = Class.create();
  403. Flog.RayTracer.Material.Chessboard.prototype = Object.extend(new Flog.RayTracer.Material.BaseMaterial, {
  404. colorEven: null,
  405. colorOdd: null,
  406. density: .5,
  407. initialize: function (a, c, b, d, e, f) {
  408. this.colorEven = a;
  409. this.colorOdd = c;
  410. this.reflection = b;
  411. this.transparency = d;
  412. this.gloss = e;
  413. this.density = f;
  414. this.hasTexture = !0
  415. },
  416. getColor: function (a, c) {
  417. return 0 > this.wrapUp(a * this.density) * this.wrapUp(c * this.density) ? this.colorEven : this.colorOdd
  418. },
  419. toString: function () {
  420. return "ChessMaterial [gloss=" + this.gloss + ", transparency=" + this.transparency +
  421. ", hasTexture=" + this.hasTexture + "]"
  422. }
  423. });
  424. "undefined" == typeof Flog && (Flog = {});
  425. "undefined" == typeof Flog.RayTracer && (Flog.RayTracer = {});
  426. "undefined" == typeof Flog.RayTracer.Shape && (Flog.RayTracer.Shape = {});
  427. Flog.RayTracer.Shape.Sphere = Class.create();
  428. Flog.RayTracer.Shape.Sphere.prototype = {
  429. initialize: function (a, c, b) {
  430. this.radius = c;
  431. this.position = a;
  432. this.material = b
  433. },
  434. intersect: function (a) {
  435. var c = new Flog.RayTracer.IntersectionInfo;
  436. c.shape = this;
  437. var b = Flog.RayTracer.Vector.prototype.subtract(a.position, this.position),
  438. d = b.dot(a.direction),
  439. b = b.dot(b) - this.radius * this.radius,
  440. b = d * d - b;
  441. 0 < b ? (c.isHit = !0, c.distance = -d - Math.sqrt(b), c.position = Flog.RayTracer.Vector.prototype.add(a.position, Flog.RayTracer.Vector.prototype.multiplyScalar(a.direction, c.distance)), c.normal =
  442. Flog.RayTracer.Vector.prototype.subtract(c.position, this.position).normalize(), c.color = this.material.getColor(0, 0)) : c.isHit = !1;
  443. return c
  444. },
  445. toString: function () {
  446. return "Sphere [position=" + this.position + ", radius=" + this.radius + "]"
  447. }
  448. };
  449. "undefined" == typeof Flog && (Flog = {});
  450. "undefined" == typeof Flog.RayTracer && (Flog.RayTracer = {});
  451. "undefined" == typeof Flog.RayTracer.Shape && (Flog.RayTracer.Shape = {});
  452. Flog.RayTracer.Shape.Plane = Class.create();
  453. Flog.RayTracer.Shape.Plane.prototype = {
  454. d: 0,
  455. initialize: function (a, c, b) {
  456. this.position = a;
  457. this.d = c;
  458. this.material = b
  459. },
  460. intersect: function (a) {
  461. var c = new Flog.RayTracer.IntersectionInfo,
  462. b = this.position.dot(a.direction);
  463. if (0 == b) return c;
  464. b = -(this.position.dot(a.position) + this.d) / b;
  465. if (0 >= b) return c;
  466. c.shape = this;
  467. c.isHit = !0;
  468. c.position = Flog.RayTracer.Vector.prototype.add(a.position, Flog.RayTracer.Vector.prototype.multiplyScalar(a.direction, b));
  469. c.normal = this.position;
  470. c.distance = b;
  471. this.material.hasTexture ? (b = new Flog.RayTracer.Vector(this.position.y,
  472. this.position.z, -this.position.x), a = b.cross(this.position), b = c.position.dot(b), a = c.position.dot(a), c.color = this.material.getColor(b, a)) : c.color = this.material.getColor(0, 0);
  473. return c
  474. },
  475. toString: function () {
  476. return "Plane [" + this.position + ", d=" + this.d + "]"
  477. }
  478. };
  479. "undefined" == typeof Flog && (Flog = {});
  480. "undefined" == typeof Flog.RayTracer && (Flog.RayTracer = {});
  481. Flog.RayTracer.IntersectionInfo = Class.create();
  482. Flog.RayTracer.IntersectionInfo.prototype = {
  483. isHit: !1,
  484. hitCount: 0,
  485. shape: null,
  486. position: null,
  487. normal: null,
  488. color: null,
  489. distance: null,
  490. initialize: function () {
  491. this.color = new Flog.RayTracer.Color(0, 0, 0)
  492. },
  493. toString: function () {
  494. return "Intersection [" + this.position + "]"
  495. }
  496. };
  497. "undefined" == typeof Flog && (Flog = {});
  498. "undefined" == typeof Flog.RayTracer && (Flog.RayTracer = {});
  499. Flog.RayTracer.Camera = Class.create();
  500. Flog.RayTracer.Camera.prototype = {
  501. position: null,
  502. lookAt: null,
  503. equator: null,
  504. up: null,
  505. screen: null,
  506. initialize: function (a, c, b) {
  507. this.position = a;
  508. this.lookAt = c;
  509. this.up = b;
  510. this.equator = c.normalize().cross(this.up);
  511. this.screen = Flog.RayTracer.Vector.prototype.add(this.position, this.lookAt)
  512. },
  513. getRay: function (a, c) {
  514. var b = Flog.RayTracer.Vector.prototype.subtract(this.screen, Flog.RayTracer.Vector.prototype.subtract(Flog.RayTracer.Vector.prototype.multiplyScalar(this.equator, a), Flog.RayTracer.Vector.prototype.multiplyScalar(this.up,
  515. c)));
  516. b.y *= -1;
  517. var d = Flog.RayTracer.Vector.prototype.subtract(b, this.position);
  518. return new Flog.RayTracer.Ray(b, d.normalize())
  519. },
  520. toString: function () {
  521. return "Ray []"
  522. }
  523. };
  524. "undefined" == typeof Flog && (Flog = {});
  525. "undefined" == typeof Flog.RayTracer && (Flog.RayTracer = {});
  526. Flog.RayTracer.Background = Class.create();
  527. Flog.RayTracer.Background.prototype = {
  528. color: null,
  529. ambience: 0,
  530. initialize: function (a, c) {
  531. this.color = a;
  532. this.ambience = c
  533. }
  534. };
  535. "undefined" == typeof Flog && (Flog = {});
  536. "undefined" == typeof Flog.RayTracer && (Flog.RayTracer = {});
  537. Flog.RayTracer.Engine = Class.create();
  538. Flog.RayTracer.Engine.prototype = {
  539. canvas: null,
  540. initialize: function (a) {
  541. this.options = Object.extend({
  542. canvasHeight: 100,
  543. canvasWidth: 100,
  544. pixelWidth: 2,
  545. pixelHeight: 2,
  546. renderDiffuse: !1,
  547. renderShadows: !1,
  548. renderHighlights: !1,
  549. renderReflections: !1,
  550. rayDepth: 2
  551. }, a || {});
  552. this.options.canvasHeight /= this.options.pixelHeight;
  553. this.options.canvasWidth /= this.options.pixelWidth
  554. },
  555. setPixel: function (a, c, b) {
  556. var d, e;
  557. d = this.options.pixelWidth;
  558. e = this.options.pixelHeight;
  559. this.canvas ? (this.canvas.fillStyle = b.toString(), this.canvas.fillRect(a *
  560. d, c * e, d, e)) : a === c && (checkNumber += b.brightness())
  561. },
  562. renderScene: function (a, c) {
  563. checkNumber = 0;
  564. this.canvas = c ? c.getContext("2d") : null;
  565. for (var b = this.options.canvasHeight, d = this.options.canvasWidth, e = 0; e < b; e++)
  566. for (var f = 0; f < d; f++) {
  567. var g = a.camera.getRay(1 * f / d * 2 - 1, 1 * e / b * 2 - 1),
  568. g = this.getPixelColor(g, a);
  569. this.setPixel(f, e, g)
  570. }
  571. if (2321 !== checkNumber) throw Error("Scene rendered incorrectly");
  572. },
  573. getPixelColor: function (a, c) {
  574. var b = this.testIntersection(a, c, null);
  575. return b.isHit ? this.rayTrace(b, a, c, 0) : c.background.color
  576. },
  577. testIntersection: function (a, c, b) {
  578. var d = 0,
  579. e = new Flog.RayTracer.IntersectionInfo;
  580. e.distance = 2E3;
  581. for (var f = 0; f < c.shapes.length; f++) {
  582. var g = c.shapes[f];
  583. g != b && (g = g.intersect(a), g.isHit && 0 <= g.distance && g.distance < e.distance && (e = g, d++))
  584. }
  585. e.hitCount = d;
  586. return e
  587. },
  588. getReflectionRay: function (a, c, b) {
  589. var d = -c.dot(b);
  590. c = Flog.RayTracer.Vector.prototype.add(Flog.RayTracer.Vector.prototype.multiplyScalar(c, 2 * d), b);
  591. return new Flog.RayTracer.Ray(a, c)
  592. },
  593. rayTrace: function (a, c, b, d) {
  594. for (var e = Flog.RayTracer.Color.prototype.multiplyScalar(a.color,
  595. b.background.ambience), f = Math.pow(10, a.shape.material.gloss + 1), g = 0; g < b.lights.length; g++) {
  596. var h = b.lights[g],
  597. l = Flog.RayTracer.Vector.prototype.subtract(h.position, a.position).normalize();
  598. if (this.options.renderDiffuse) {
  599. var m = l.dot(a.normal);
  600. 0 < m && (e = Flog.RayTracer.Color.prototype.add(e, Flog.RayTracer.Color.prototype.multiply(a.color, Flog.RayTracer.Color.prototype.multiplyScalar(h.color, m))))
  601. }
  602. if (d <= this.options.rayDepth && this.options.renderReflections && 0 < a.shape.material.reflection) {
  603. var m = this.getReflectionRay(a.position,
  604. a.normal, c.direction),
  605. q = this.testIntersection(m, b, a.shape);
  606. q.color = q.isHit && 0 < q.distance ? this.rayTrace(q, m, b, d + 1) : b.background.color;
  607. e = Flog.RayTracer.Color.prototype.blend(e, q.color, a.shape.material.reflection)
  608. }
  609. m = new Flog.RayTracer.IntersectionInfo;
  610. this.options.renderShadows && (l = new Flog.RayTracer.Ray(a.position, l), m = this.testIntersection(l, b, a.shape), m.isHit && m.shape != a.shape && (e = Flog.RayTracer.Color.prototype.multiplyScalar(e, .5), e = Flog.RayTracer.Color.prototype.addScalar(e, .5 * Math.pow(m.shape.material.transparency,
  611. .5))));
  612. this.options.renderHighlights && !m.isHit && 0 < a.shape.material.gloss && (l = Flog.RayTracer.Vector.prototype.subtract(a.shape.position, h.position).normalize(), m = Flog.RayTracer.Vector.prototype.subtract(b.camera.position, a.shape.position).normalize(), l = Flog.RayTracer.Vector.prototype.subtract(m, l).normalize(), l = Math.pow(Math.max(a.normal.dot(l), 0), f), e = Flog.RayTracer.Color.prototype.add(Flog.RayTracer.Color.prototype.multiplyScalar(h.color, l), e))
  613. }
  614. e.limit();
  615. return e
  616. }
  617. };
  618. function renderScene() {
  619. var a = new Flog.RayTracer.Scene();
  620. a.camera = new Flog.RayTracer.Camera(new Flog.RayTracer.Vector(0, 0, -15), new Flog.RayTracer.Vector(-.2, 0, 5), new Flog.RayTracer.Vector(0, 1, 0));
  621. a.background = new Flog.RayTracer.Background(new Flog.RayTracer.Color(.5, .5, .5), .4);
  622. var c = new Flog.RayTracer.Shape.Sphere(new Flog.RayTracer.Vector(-1.5, 1.5, 2), 1.5, new Flog.RayTracer.Material.Solid(new Flog.RayTracer.Color(0, .5, .5), .3, 0, 0, 2)),
  623. b = new Flog.RayTracer.Shape.Sphere(new Flog.RayTracer.Vector(1, .25, 1),
  624. .5, new Flog.RayTracer.Material.Solid(new Flog.RayTracer.Color(.9, .9, .9), .1, 0, 0, 1.5)),
  625. d = new Flog.RayTracer.Shape.Plane((new Flog.RayTracer.Vector(.1, .9, -.5)).normalize(), 1.2, new Flog.RayTracer.Material.Chessboard(new Flog.RayTracer.Color(1, 1, 1), new Flog.RayTracer.Color(0, 0, 0), .2, 0, 1, .7));
  626. a.shapes.push(d);
  627. a.shapes.push(c);
  628. a.shapes.push(b);
  629. c = new Flog.RayTracer.Light(new Flog.RayTracer.Vector(5, 10, -1), new Flog.RayTracer.Color(.8, .8, .8));
  630. b = new Flog.RayTracer.Light(new Flog.RayTracer.Vector(-3, 5, -15), new Flog.RayTracer.Color(.8,
  631. .8, .8), 100);
  632. a.lights.push(c);
  633. a.lights.push(b);
  634. c = ["5", "5"];
  635. (new Flog.RayTracer.Engine({
  636. canvasWidth: 100,
  637. canvasHeight: 100,
  638. pixelWidth: c[0],
  639. pixelHeight: c[1],
  640. renderDiffuse: !0,
  641. renderHighlights: !0,
  642. renderShadows: !0,
  643. renderReflections: !0,
  644. rayDepth: 2
  645. })).renderScene(a, null, 0)
  646. };
  647. ////////////////////////////////////////////////////////////////////////////////
  648. // Runner
  649. ////////////////////////////////////////////////////////////////////////////////
  650. var success = true;
  651. function NotifyStart(name) { }
  652. function NotifyError(name, error) {
  653. WScript.Echo(name + " : ERROR : " + error.stack);
  654. success = false;
  655. }
  656. function NotifyResult(name, score) {
  657. if (success) {
  658. WScript.Echo("### SCORE:", score);
  659. }
  660. }
  661. function NotifyScore(score) { }
  662. BenchmarkSuite.RunSuites({
  663. NotifyStart: NotifyStart,
  664. NotifyError: NotifyError,
  665. NotifyResult: NotifyResult,
  666. NotifyScore: NotifyScore
  667. });