@awayjs/renderer
Version:
Renderer for AwayJS
157 lines (128 loc) • 3.13 kB
text/typescript
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;
}
}