Subversion Repositories Applications.papyrus

Rev

Blame | Last modification | View Log | RSS feed

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.
});

}