UNPKG

@awayjs/renderer

Version:
157 lines (128 loc) 3.13 kB
import { IRenderEntitySorter } from './IRenderEntitySorter'; import { _Render_RenderableBase } from '../base/_Render_RenderableBase'; /** * @class away.sort.RenderableMergeSort */ export class RenderableMergeSort implements IRenderEntitySorter { public sortBlendedRenderables(head: _Render_RenderableBase): _Render_RenderableBase { let headB: _Render_RenderableBase; let fast: _Render_RenderableBase; let slow: _Render_RenderableBase; if (!head || !head.next) { return head; } // split in two sublists slow = head; fast = head.next; while (fast) { fast = fast.next; if (fast) { slow = slow.next; fast = fast.next; } } headB = slow.next; slow.next = null; // recurse head = this.sortBlendedRenderables(head); headB = this.sortBlendedRenderables(headB); // merge sublists while respecting order let result: _Render_RenderableBase; let curr: _Render_RenderableBase; let l: _Render_RenderableBase; if (!head) return headB; if (!headB) return head; while (head && headB) { if (head.entity.zIndex < headB.entity.zIndex) { l = head; head = head.next; } else { l = headB; headB = headB.next; } if (!result) result = l; else curr.next = l; curr = l; } if (head) curr.next = head; else if (headB) curr.next = headB; return result; } public sortOpaqueRenderables(head: _Render_RenderableBase): _Render_RenderableBase { let headB: _Render_RenderableBase; let fast: _Render_RenderableBase, slow: _Render_RenderableBase; if (!head || !head.next) { return head; } // split in two sublists slow = head; fast = head.next; while (fast) { fast = fast.next; if (fast) { slow = slow.next; fast = fast.next; } } headB = slow.next; slow.next = null; // recurse head = this.sortOpaqueRenderables(head); headB = this.sortOpaqueRenderables(headB); // merge sublists while respecting order let result: _Render_RenderableBase; let curr: _Render_RenderableBase; let l: _Render_RenderableBase; let cmp: number = 0; if (!head) return headB; if (!headB) return head; while (head && headB && head != null && headB != null) { // first sort per render order id (reduces program3D switches), // then on render object id (reduces setting props), // then on zIndex (reduces overdraw) const aid: number = head.renderOrderId; const bid: number = headB.renderOrderId; if (aid == bid) { const ma: number = head.materialID; const mb: number = headB.materialID; if (ma == mb) { if (head.entity.zIndex < headB.entity.zIndex) cmp = 1; else cmp = -1; } else if (ma > mb) { cmp = 1; } else { cmp = -1; } } else if (aid > bid) { cmp = 1; } else { cmp = -1; } if (cmp < 0) { l = head; head = head.next; } else { l = headB; headB = headB.next; } if (!result) { result = l; curr = l; } else { curr.next = l; curr = l; } } if (head) curr.next = head; else if (headB) curr.next = headB; return result; } }