package org.papervision3d.core.render.data { import flash.display.Graphics; import flash.geom.Rectangle; import org.papervision3d.core.render.command.RenderableListItem; import org.papervision3d.objects.DisplayObject3D; /** * Quadrant tree node */ public final class student_ar_org_papervision3d_core_render_data_QuadTreeNode { private var render_center_length:int = -1; private var render_center_index:int = -1; private var halfwidth:Number; private var halfheight:Number; private var level:int; public var maxlevel:int = 4; private function render_other(limit:Number, renderSessionData:RenderSessionData, graphics:Graphics):void { if (lefttopFlag) lefttop.render(limit, renderSessionData, graphics); if (leftbottomFlag) leftbottom.render(limit, renderSessionData, graphics); if (righttopFlag) righttop.render(limit, renderSessionData, graphics); if (rightbottomFlag) rightbottom.render(limit, renderSessionData, graphics); } /** * Array of primitives that lie in the center of the quadrant. */ public var center:Array; /** * The quadrant tree node for the top left quadrant. */ public var lefttop:student_ar_org_papervision3d_core_render_data_QuadTreeNode; /** * The quadrant tree node for the bottom left quadrant. */ public var leftbottom:student_ar_org_papervision3d_core_render_data_QuadTreeNode; /** * The quadrant tree node for the top right quadrant. */ public var righttop:student_ar_org_papervision3d_core_render_data_QuadTreeNode; /** * The quadrant tree node for the bottom right quadrant. */ public var rightbottom:student_ar_org_papervision3d_core_render_data_QuadTreeNode; /** * Determines if the bounds of the top left quadrant need re-calculating. */ public var lefttopFlag:Boolean; /** * Determines if the bounds of the bottom left quadrant need re-calculating. */ public var leftbottomFlag:Boolean; /** * Determines if the bounds of the top right quadrant need re-calculating. */ public var righttopFlag:Boolean; /** * Determines if the bounds of the bottom right quadrant need re-calculating. */ public var rightbottomFlag:Boolean; /** * Determines if the quadrant node contains only one source. */ public var onlysourceFlag:Boolean = true; /** * hold the 3d object referenced when onlysourceFlag is true. */ public var onlysource:DisplayObject3D; /** * The x coordinate of the quadrant division. */ public var xdiv:Number; /** * The x coordinate of the quadrant division. */ public var ydiv:Number; /** * The quadrant parent. */ public var parent:student_ar_org_papervision3d_core_render_data_QuadTreeNode; /** * Placeholder function for creating new quadrant node from a cache of objects. * Saves recreating objects and GC problems. */ public var create:Function; /** * Says if node has content or not */ public var hasContent:Boolean = false; /** * Creates a new PrimitiveQuadrantTreeNode object. * * @param xdiv The x coordinate for the division between left and right child quadrants. * @param ydiv The y coordinate for the division between top and bottom child quadrants. * @param width The width of the quadrant node. * @param xdiv The height of the quadrant node. * @param level The iteration number of the quadrant node. * @param parent The parent quadrant of the quadrant node. * @param maxLevel The deepest a Node can go */ public function student_ar_org_papervision3d_core_render_data_QuadTreeNode(xdiv:Number, ydiv:Number, width:Number, height:Number, level:int, parent:student_ar_org_papervision3d_core_render_data_QuadTreeNode = null, maxLevel:uint = 4) { this.level = level; this.xdiv = xdiv; this.ydiv = ydiv; halfwidth = width / 2; halfheight = height / 2; this.parent = parent; this.maxlevel = maxLevel; } /** * Adds a primitive to the quadrant */ public function push(pri:RenderableListItem):void { hasContent = true; if (onlysourceFlag) { if (onlysource != null && onlysource != pri.instance) onlysourceFlag = false; onlysource = pri.instance; } if (level < maxlevel) { if (pri.maxX <= xdiv) { if (pri.maxY <= ydiv) { if (lefttop == null) { lefttopFlag = true; lefttop = new student_ar_org_papervision3d_core_render_data_QuadTreeNode(xdiv - halfwidth/2, ydiv - halfheight/2, halfwidth, halfheight, level+1, this, maxlevel); } else if (!lefttopFlag) { lefttopFlag = true; lefttop.reset(xdiv - halfwidth/2, ydiv - halfheight/2, halfwidth, halfheight, maxlevel); } lefttop.push(pri); return; } else if (pri.minY >= ydiv) { if (leftbottom == null) { leftbottomFlag = true; leftbottom = new student_ar_org_papervision3d_core_render_data_QuadTreeNode(xdiv - halfwidth/2, ydiv + halfheight/2, halfwidth, halfheight, level+1, this, maxlevel); } else if (!leftbottomFlag) { leftbottomFlag = true; leftbottom.reset(xdiv - halfwidth/2, ydiv + halfheight/2, halfwidth, halfheight, maxlevel); } leftbottom.push(pri); return; } } else if (pri.minX >= xdiv) { if (pri.maxY <= ydiv) { if (righttop == null) { righttopFlag = true; righttop = new student_ar_org_papervision3d_core_render_data_QuadTreeNode(xdiv + halfwidth/2, ydiv - halfheight/2, halfwidth, halfheight, level+1, this, maxlevel); } else if (!righttopFlag) { righttopFlag = true; righttop.reset(xdiv + halfwidth/2, ydiv - halfheight/2, halfwidth, halfheight, maxlevel); } righttop.push(pri); return; } else if (pri.minY >= ydiv) { if (rightbottom == null) { rightbottomFlag = true; rightbottom = new student_ar_org_papervision3d_core_render_data_QuadTreeNode(xdiv + halfwidth/2, ydiv + halfheight/2, halfwidth, halfheight, level+1, this, maxlevel); } else if (!rightbottomFlag) { rightbottomFlag = true; rightbottom.reset(xdiv + halfwidth/2, ydiv + halfheight/2, halfwidth, halfheight, maxlevel); } rightbottom.push(pri); return; } } } //no quadrant, store in center array if (center == null) center = new Array(); center.push(pri); pri.quadrant = this; } /** * Clears the quadrant of all primitives and child nodes */ public function reset(xdiv:Number, ydiv:Number, width:Number, height:Number, maxLevel:uint):void { this.xdiv = xdiv; this.ydiv = ydiv; halfwidth = width / 2; halfheight = height / 2; lefttopFlag = false; leftbottomFlag = false; righttopFlag = false; rightbottomFlag = false; onlysourceFlag = true; onlysource = null; render_center_length = -1; render_center_index = -1; hasContent = false; maxlevel = maxLevel; } public function getRect():Rectangle{ return new Rectangle(xdiv, ydiv, halfwidth*2, halfheight*2); } /** * Sorts and renders the contents of the quadrant tree */ public function render(limit:Number, renderSessionData:RenderSessionData, graphics:Graphics):void { if (render_center_length == -1) { if (center != null) { render_center_length = center.length; if (render_center_length > 1) center.sortOn("screenZ", Array.DESCENDING | Array.NUMERIC); } else render_center_length = 0; render_center_index = 0; } while (render_center_index < render_center_length) { var pri:RenderableListItem = center[render_center_index]; if (pri.screenZ < limit) break; render_other(pri.screenZ, renderSessionData, graphics); pri.render(renderSessionData, graphics); renderSessionData.viewPort.lastRenderList.push(pri); render_center_index++; } if (render_center_index == render_center_length) center = null; render_other(limit, renderSessionData, graphics); } } }