scheduler.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. define("dojox/gfx3d/scheduler", [
  2. "dojo/_base/lang",
  3. "dojo/_base/array", // dojo.forEach, dojo.every
  4. "dojo/_base/declare", // dojo.declare
  5. "./_base",
  6. "./vector"
  7. ], function(lang, arrayUtil, declare, gfx3d, vectorUtil){
  8. gfx3d.scheduler = {
  9. zOrder: function(buffer, order){
  10. order = order ? order : gfx3d.scheduler.order;
  11. buffer.sort(function(a, b){
  12. return order(b) - order(a);
  13. });
  14. return buffer;
  15. },
  16. bsp: function(buffer, outline){
  17. // console.debug("BSP scheduler");
  18. outline = outline ? outline : gfx3d.scheduler.outline;
  19. var p = new gfx3d.scheduler.BinarySearchTree(buffer[0], outline);
  20. arrayUtil.forEach(buffer.slice(1), function(item){ p.add(item, outline); });
  21. return p.iterate(outline);
  22. },
  23. // default implementation
  24. order: function(it){
  25. return it.getZOrder();
  26. },
  27. outline: function(it){
  28. return it.getOutline();
  29. }
  30. };
  31. var BST = declare("dojox.gfx3d.scheduler.BinarySearchTree", null, {
  32. constructor: function(obj, outline){
  33. // summary: build the binary search tree, using binary space partition algorithm.
  34. // The idea is for any polygon, for example, (a, b, c), the space is divided by
  35. // the plane into two space: plus and minus.
  36. //
  37. // for any arbitary vertex p, if(p - a) dotProduct n = 0, p is inside the plane,
  38. // > 0, p is in the plus space, vice versa for minus space.
  39. // n is the normal vector that is perpendicular the plate, defined as:
  40. // n = ( b - a) crossProduct ( c - a )
  41. //
  42. // in this implementation, n is declared as normal, ,a is declared as orient.
  43. //
  44. // obj: object: dojox.gfx3d.Object
  45. this.plus = null;
  46. this.minus = null;
  47. this.object = obj;
  48. var o = outline(obj);
  49. this.orient = o[0];
  50. this.normal = vectorUtil.normalize(o);
  51. },
  52. add: function(obj, outline){
  53. var epsilon = 0.5,
  54. o = outline(obj),
  55. v = vectorUtil,
  56. n = this.normal,
  57. a = this.orient,
  58. BST = gfx3d.scheduler.BinarySearchTree;
  59. if(
  60. arrayUtil.every(o, function(item){
  61. return Math.floor(epsilon + v.dotProduct(n, v.substract(item, a))) <= 0;
  62. })
  63. ){
  64. if(this.minus){
  65. this.minus.add(obj, outline);
  66. }else{
  67. this.minus = new BST(obj, outline);
  68. }
  69. }else if(
  70. arrayUtil.every(o, function(item){
  71. return Math.floor(epsilon + v.dotProduct(n, v.substract(item, a))) >= 0;
  72. })
  73. ){
  74. if(this.plus){
  75. this.plus.add(obj, outline);
  76. } else {
  77. this.plus = new BST(obj, outline);
  78. }
  79. }else{
  80. /*
  81. arrayUtil.forEach(o, function(item){
  82. console.debug(v.dotProduct(n, v.substract(item, a)));
  83. });
  84. */
  85. throw "The case: polygon cross siblings' plate is not implemented yet";
  86. }
  87. },
  88. iterate: function(outline){
  89. var epsilon = 0.5;
  90. var v = vectorUtil;
  91. var sorted = [];
  92. var subs = null;
  93. // FIXME: using Infinity here?
  94. var view = {x: 0, y: 0, z: -10000};
  95. if(Math.floor( epsilon + v.dotProduct(this.normal, v.substract(view, this.orient))) <= 0){
  96. subs = [this.plus, this.minus];
  97. }else{
  98. subs = [this.minus, this.plus];
  99. }
  100. if(subs[0]){
  101. sorted = sorted.concat(subs[0].iterate());
  102. }
  103. sorted.push(this.object);
  104. if(subs[1]){
  105. sorted = sorted.concat(subs[1].iterate());
  106. }
  107. return sorted;
  108. }
  109. });
  110. gfx3d.drawer = {
  111. conservative: function(todos, objects, viewport){
  112. // console.debug('conservative draw');
  113. arrayUtil.forEach(this.objects, function(item){
  114. item.destroy();
  115. });
  116. arrayUtil.forEach(objects, function(item){
  117. item.draw(viewport.lighting);
  118. });
  119. },
  120. chart: function(todos, objects, viewport){
  121. // NOTE: ondemand may require the todos' objects to use setShape
  122. // to redraw themselves to maintain the z-order.
  123. // console.debug('chart draw');
  124. arrayUtil.forEach(this.todos, function(item){
  125. item.draw(viewport.lighting);
  126. });
  127. }
  128. // More aggrasive optimization may re-order the DOM nodes using the order
  129. // of objects, and only elements of todos call setShape.
  130. };
  131. var api = {
  132. scheduler: gfx3d.scheduler,
  133. drawer: gfx3d.drawer,
  134. BinarySearchTree: BST
  135. };
  136. return api;
  137. });