143 lines
3.7 KiB
JavaScript
143 lines
3.7 KiB
JavaScript
|
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,
|
||
|
BST = dojox.gfx3d.scheduler.BinarySearchTree;
|
||
|
|
||
|
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 BST(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 BST(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.
|
||
|
});
|