123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- define("dojox/gfx3d/scheduler", [
- "dojo/_base/lang",
- "dojo/_base/array", // dojo.forEach, dojo.every
- "dojo/_base/declare", // dojo.declare
- "./_base",
- "./vector"
- ], function(lang, arrayUtil, declare, gfx3d, vectorUtil){
- gfx3d.scheduler = {
- zOrder: function(buffer, order){
- order = order ? order : 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 : gfx3d.scheduler.outline;
- var p = new gfx3d.scheduler.BinarySearchTree(buffer[0], outline);
- arrayUtil.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();
- }
- };
- var BST = 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 = vectorUtil.normalize(o);
- },
- add: function(obj, outline){
- var epsilon = 0.5,
- o = outline(obj),
- v = vectorUtil,
- n = this.normal,
- a = this.orient,
- BST = gfx3d.scheduler.BinarySearchTree;
- if(
- arrayUtil.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(
- arrayUtil.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{
- /*
- arrayUtil.forEach(o, function(item){
- console.debug(v.dotProduct(n, v.substract(item, a)));
- });
- */
- throw "The case: polygon cross siblings' plate is not implemented yet";
- }
- },
- iterate: function(outline){
- var epsilon = 0.5;
- var v = vectorUtil;
- 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;
- }
- });
- gfx3d.drawer = {
- conservative: function(todos, objects, viewport){
- // console.debug('conservative draw');
- arrayUtil.forEach(this.objects, function(item){
- item.destroy();
- });
- arrayUtil.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');
- arrayUtil.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.
- };
- var api = {
- scheduler: gfx3d.scheduler,
- drawer: gfx3d.drawer,
- BinarySearchTree: BST
- };
- return api;
- });
|