Rewrote the iso sorting algorithm yet again. Now it's less efficient but

actually works. (Or so we hope.) Yay!


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2348 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2003-03-30 02:15:13 +00:00
parent 73b16bc018
commit 17b3922946
@@ -1,5 +1,5 @@
//
// $Id: DirtyItemList.java,v 1.22 2003/02/12 05:46:05 mdb Exp $
// $Id: DirtyItemList.java,v 1.23 2003/03/30 02:15:13 mdb Exp $
package com.threerings.miso.client;
@@ -104,16 +104,45 @@ public class DirtyItemList
"[items=" + toString(_yitems) + "].");
}
// sort items into proper render order
_items.sort(_rcomp);
// sort the items according to the depth of the rear-most tile
_ditems.addAll(_items);
_ditems.sort(REAR_DEPTH_COMP);
// now insertion sort the items from back to front into the
// render-sorted array
_items.clear();
POS_LOOP:
for (int ii = 0; ii < size; ii++) {
DirtyItem item = (DirtyItem)_ditems.get(ii);
for (int rr = _items.size()-1; rr >= 0; rr--) {
DirtyItem pitem = (DirtyItem)_items.get(rr);
// if we render in front of this item, insert
// ourselves immediately following it
if (_rcomp.compare(item, pitem) > 0) {
_items.add(rr+1, item);
continue POS_LOOP;
}
}
// we don't render in front of anyone, so we go at the
// front of the list
_items.add(0, item);
}
// clear out our temporary arrays
_xitems.clear();
_yitems.clear();
_ditems.clear();
}
if (DEBUG_SORT) {
Log.info("Sorted for render [items=" + toString(_items) + "].");
for (int ii = 0, ll = _items.size()-1; ii < ll; ii++) {
DirtyItem a = (DirtyItem)_items.get(ii);
DirtyItem b = (DirtyItem)_items.get(ii+1);
if (_rcomp.compare(a, b) > 0) {
Log.warning("Invalid ordering [a=" + a + ", b=" + b + "].");
}
}
}
}
@@ -167,25 +196,33 @@ public class DirtyItemList
}
}
/**
* Returns an abbreviated string representation of the given dirty
* item describing only its origin coordinates and render priority.
* Intended for debugging purposes.
*/
protected static String toString (DirtyItem a)
{
StringBuffer buf = new StringBuffer("[");
toString(buf, a);
return buf.append("]").toString();
}
/**
* Returns an abbreviated string representation of the two given dirty
* items describing each by only its origin coordinates. Intended for
* debugging purposes.
* items. See {@link #toString(DirtyItem}.
*/
protected static String toString (DirtyItem a, DirtyItem b)
{
StringBuffer buf = new StringBuffer();
buf.append("[(ox=").append(a.ox);
buf.append(", oy=").append(a.oy).append("), ");
buf.append("(ox=").append(b.ox);
buf.append(", oy=").append(b.oy).append(")");
StringBuffer buf = new StringBuffer("[");
toString(buf, a);
toString(buf, b);
return buf.append("]").toString();
}
/**
* Returns an abbreviated string representation of the given dirty
* items describing each by only its origin coordinates. Intended for
* debugging purposes.
* items. See {@link #toString(DirtyItem}.
*/
protected static String toString (SortableArrayList items)
{
@@ -193,8 +230,7 @@ public class DirtyItemList
buf.append("[");
for (int ii = 0; ii < items.size(); ii++) {
DirtyItem item = (DirtyItem)items.get(ii);
buf.append("(ox=").append(item.ox);
buf.append(", oy=").append(item.oy).append(")");
toString(buf, item);
if (ii < (items.size() - 1)) {
buf.append(", ");
}
@@ -202,6 +238,13 @@ public class DirtyItemList
return buf.append("]").toString();
}
/** Helper function for {@link #toString(DirtyItem)}. */
protected static void toString (StringBuffer buf, DirtyItem item)
{
buf.append("(o:+").append(item.ox).append("+").append(item.oy);
buf.append(" p:").append(item.getRenderPriority()).append(")");
}
/**
* A class to hold the items inserted in the dirty list along with
* all of the information necessary to render their dirty regions
@@ -303,6 +346,28 @@ public class DirtyItemList
}
}
/**
* Returns the "depth" of our rear-most tile.
*/
public int getRearDepth ()
{
return ry + lx;
}
/**
* Returns the render priority for this dirty item. It will be
* zero unless this is a display object which may have a custom
* render priority.
*/
public int getRenderPriority ()
{
if (obj instanceof DisplayObjectInfo) {
return ((DisplayObjectInfo)obj).getPriority();
} else {
return 0;
}
}
/**
* Releases all references held by this dirty item so that it
* doesn't inadvertently hold on to any objects while waiting to
@@ -385,16 +450,7 @@ public class DirtyItemList
// if they do overlap, incorporate render priority; assume
// non-display objects have a render priority of zero
int aprio = 0;
if (da.obj instanceof DisplayObjectInfo) {
aprio = ((DisplayObjectInfo)da.obj).getPriority();
}
int bprio = 0;
if (db.obj instanceof DisplayObjectInfo) {
bprio = ((DisplayObjectInfo)db.obj).getPriority();
}
return aprio - bprio;
return da.getRenderPriority() - db.getRenderPriority();
}
/** The axis this comparator sorts on. */
@@ -415,6 +471,23 @@ public class DirtyItemList
DirtyItem da = (DirtyItem)a;
DirtyItem db = (DirtyItem)b;
// if the two objects are scene objects and they overlap, we
// compare them solely based on their human assigned priority
if ((da.obj instanceof DisplayObjectInfo) &&
(db.obj instanceof DisplayObjectInfo)) {
DisplayObjectInfo soa = (DisplayObjectInfo)da.obj;
DisplayObjectInfo sob = (DisplayObjectInfo)db.obj;
if (IsoUtil.objectFootprintsOverlap(soa, sob)) {
int result = soa.getPriority() - sob.getPriority();
if (DEBUG_COMPARE) {
String items = DirtyItemList.toString(da, db);
Log.info("compare: overlapping [result=" + result +
", items=" + items + "].");
}
return result;
}
}
// check for partitioning objects on the y-axis
int result = comparePartitioned(Y_AXIS, da, db);
if (result != 0) {
@@ -587,28 +660,15 @@ public class DirtyItemList
}
}
// if the two objects are scene objects and they overlap, we
// compare them solely based on their human assigned render
// priority scene; this allows us to avoid all sorts of sticky
// business wherein the render order between two overlapping
// objects cannot be determined without a z-buffer
if ((da.obj instanceof DisplayObjectInfo) &&
(db.obj instanceof DisplayObjectInfo)) {
DisplayObjectInfo soa = (DisplayObjectInfo)da.obj;
DisplayObjectInfo sob = (DisplayObjectInfo)db.obj;
if (IsoUtil.objectFootprintsOverlap(soa, sob)) {
return (soa.getPriority() - sob.getPriority());
}
}
// otherwise use a consistent ordering for non-overlappers;
// see narya/docs/miso/render_sort_diagram.png for more info
if (da.lx > db.ox) {
if (db.lx <= da.ox && db.ry <= da.oy) {
return 1;
} else if (da.ry > db.oy) {
return (db.lx > da.ox) ? -1 : 1;
} else if (db.lx >= da.lx && db.ry >= da.ry) {
return -1;
} else {
return 0;
}
return -1;
}
}
@@ -624,6 +684,9 @@ public class DirtyItemList
/** The list of dirty items sorted by y-position. */
protected SortableArrayList _yitems = new SortableArrayList();
/** The list of dirty items sorted by rear-depth. */
protected SortableArrayList _ditems = new SortableArrayList();
/** The render comparator we'll use for our final, magical sort. */
protected Comparator _rcomp = new RenderComparator();
@@ -659,4 +722,13 @@ public class DirtyItemList
* y-coordinate order. */
protected static final Comparator ORIGIN_Y_COMP =
new OriginComparator(Y_AXIS);
/** The comparator used to sort dirty items in ascending "rear-depth"
* order. */
protected static final Comparator REAR_DEPTH_COMP = new Comparator() {
public int compare (Object o1, Object o2) {
return (((DirtyItem)o1).getRearDepth() -
((DirtyItem)o2).getRearDepth());
}
};
}