New file |
0,0 → 1,126 |
if(!dojo._hasResource["dojox.gfx3d.scheduler"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. |
dojo._hasResource["dojox.gfx3d.scheduler"] = true; |
dojo.provide("dojox.gfx3d.scheduler"); |
dojo.provide("dojox.gfx3d.drawer"); |
dojo.require("dojox.gfx3d.vector"); |
|
dojo.mixin(dojox.gfx3d.scheduler, { |
zOrder: function(buffer, order){ |
order = order ? order : dojox.gfx3d.scheduler.order; |
buffer.sort(function(a, b){ |
return order(b) - order(a); |
}); |
return buffer; |
}, |
|
bsp: function(buffer, outline){ |
console.debug("BSP scheduler"); |
outline = outline ? outline : dojox.gfx3d.scheduler.outline; |
var p = new dojox.gfx3d.scheduler.BinarySearchTree(buffer[0], outline); |
dojo.forEach(buffer.slice(1), function(item){ p.add(item, outline); }); |
return p.iterate(outline); |
}, |
|
// default implementation |
order: function(it){ |
return it.getZOrder(); |
}, |
|
outline: function(it){ |
return it.getOutline(); |
} |
|
}); |
|
dojo.declare("dojox.gfx3d.scheduler.BinarySearchTree", null, { |
constructor: function(obj, outline){ |
// summary: build the binary search tree, using binary space partition algorithm. |
// The idea is for any polygon, for example, (a, b, c), the space is divided by |
// the plane into two space: plus and minus. |
// |
// for any arbitary vertex p, if(p - a) dotProduct n = 0, p is inside the plane, |
// > 0, p is in the plus space, vice versa for minus space. |
// n is the normal vector that is perpendicular the plate, defined as: |
// n = ( b - a) crossProduct ( c - a ) |
// |
// in this implementation, n is declared as normal, ,a is declared as orient. |
// |
// obj: object: dojox.gfx3d.Object |
this.plus = null; |
this.minus = null; |
this.object = obj; |
|
var o = outline(obj); |
this.orient = o[0]; |
this.normal = dojox.gfx3d.vector.normalize(o); |
}, |
|
add: function(obj, outline){ |
var epsilon = 0.5, o = outline(obj), v = dojox.gfx3d.vector, n = this.normal, a = this.orient; |
|
if(dojo.every(o, function(item){ return Math.floor(epsilon + v.dotProduct(n, v.substract(item, a))) <= 0; })){ |
if(this.minus){ |
this.minus.add(obj, outline); |
} else { |
this.minus = new dojox.gfx3d.scheduler.BinarySearchTree(obj, outline); |
} |
} else if(dojo.every(o, function(item){ return Math.floor(epsilon + v.dotProduct(n, v.substract(item, a))) >= 0; })){ |
if(this.plus){ |
this.plus.add(obj, outline); |
} else { |
this.plus = new dojox.gfx3d.scheduler.BinarySearchTree(obj, outline); |
} |
} else { |
dojo.forEach(o, function(item){ console.debug(v.dotProduct(n, v.substract(item, a))); }); |
throw "The case: polygon cross siblings' plate is not implemneted yet"; |
} |
}, |
|
iterate: function(outline){ |
var epsilon = 0.5; |
var v = dojox.gfx3d.vector; |
var sorted = []; |
var subs = null; |
// FIXME: using Infinity here? |
var view = {x: 0, y: 0, z: -10000}; |
if(Math.floor( epsilon + v.dotProduct(this.normal, v.substract(view, this.orient))) <= 0){ |
subs = [this.plus, this.minus]; |
} else { |
subs = [this.minus, this.plus]; |
} |
|
if(subs[0]){ |
sorted = sorted.concat(subs[0].iterate()); |
} |
sorted.push(this.object); |
if(subs[1]){ |
sorted = sorted.concat(subs[1].iterate()); |
} |
return sorted; |
} |
|
}); |
|
dojo.mixin(dojox.gfx3d.drawer, { |
conservative: function(todos, objects, viewport){ |
console.debug('conservative draw'); |
dojo.forEach(this.objects, function(item){ |
item.destroy(); |
}); |
dojo.forEach(objects, function(item){ |
item.draw(viewport.lighting); |
}); |
}, |
chart: function(todos, objects, viewport){ |
// NOTE: ondemand may require the todos' objects to use setShape |
// to redraw themselves to maintain the z-order. |
console.debug('chart draw'); |
dojo.forEach(this.todos, function(item){ |
item.draw(viewport.lighting); |
}); |
} |
// More aggrasive optimization may re-order the DOM nodes using the order |
// of objects, and only elements of todos call setShape. |
}); |
|
} |