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:
@@ -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;
|
package com.threerings.miso.client;
|
||||||
|
|
||||||
@@ -104,16 +104,45 @@ public class DirtyItemList
|
|||||||
"[items=" + toString(_yitems) + "].");
|
"[items=" + toString(_yitems) + "].");
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort items into proper render order
|
// sort the items according to the depth of the rear-most tile
|
||||||
_items.sort(_rcomp);
|
_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
|
// clear out our temporary arrays
|
||||||
_xitems.clear();
|
_xitems.clear();
|
||||||
_yitems.clear();
|
_yitems.clear();
|
||||||
|
_ditems.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DEBUG_SORT) {
|
if (DEBUG_SORT) {
|
||||||
Log.info("Sorted for render [items=" + toString(_items) + "].");
|
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
|
* Returns an abbreviated string representation of the two given dirty
|
||||||
* items describing each by only its origin coordinates. Intended for
|
* items. See {@link #toString(DirtyItem}.
|
||||||
* debugging purposes.
|
|
||||||
*/
|
*/
|
||||||
protected static String toString (DirtyItem a, DirtyItem b)
|
protected static String toString (DirtyItem a, DirtyItem b)
|
||||||
{
|
{
|
||||||
StringBuffer buf = new StringBuffer();
|
StringBuffer buf = new StringBuffer("[");
|
||||||
buf.append("[(ox=").append(a.ox);
|
toString(buf, a);
|
||||||
buf.append(", oy=").append(a.oy).append("), ");
|
toString(buf, b);
|
||||||
buf.append("(ox=").append(b.ox);
|
|
||||||
buf.append(", oy=").append(b.oy).append(")");
|
|
||||||
return buf.append("]").toString();
|
return buf.append("]").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an abbreviated string representation of the given dirty
|
* Returns an abbreviated string representation of the given dirty
|
||||||
* items describing each by only its origin coordinates. Intended for
|
* items. See {@link #toString(DirtyItem}.
|
||||||
* debugging purposes.
|
|
||||||
*/
|
*/
|
||||||
protected static String toString (SortableArrayList items)
|
protected static String toString (SortableArrayList items)
|
||||||
{
|
{
|
||||||
@@ -193,8 +230,7 @@ public class DirtyItemList
|
|||||||
buf.append("[");
|
buf.append("[");
|
||||||
for (int ii = 0; ii < items.size(); ii++) {
|
for (int ii = 0; ii < items.size(); ii++) {
|
||||||
DirtyItem item = (DirtyItem)items.get(ii);
|
DirtyItem item = (DirtyItem)items.get(ii);
|
||||||
buf.append("(ox=").append(item.ox);
|
toString(buf, item);
|
||||||
buf.append(", oy=").append(item.oy).append(")");
|
|
||||||
if (ii < (items.size() - 1)) {
|
if (ii < (items.size() - 1)) {
|
||||||
buf.append(", ");
|
buf.append(", ");
|
||||||
}
|
}
|
||||||
@@ -202,6 +238,13 @@ public class DirtyItemList
|
|||||||
return buf.append("]").toString();
|
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
|
* A class to hold the items inserted in the dirty list along with
|
||||||
* all of the information necessary to render their dirty regions
|
* 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
|
* Releases all references held by this dirty item so that it
|
||||||
* doesn't inadvertently hold on to any objects while waiting to
|
* 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
|
// if they do overlap, incorporate render priority; assume
|
||||||
// non-display objects have a render priority of zero
|
// non-display objects have a render priority of zero
|
||||||
int aprio = 0;
|
return da.getRenderPriority() - db.getRenderPriority();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The axis this comparator sorts on. */
|
/** The axis this comparator sorts on. */
|
||||||
@@ -415,6 +471,23 @@ public class DirtyItemList
|
|||||||
DirtyItem da = (DirtyItem)a;
|
DirtyItem da = (DirtyItem)a;
|
||||||
DirtyItem db = (DirtyItem)b;
|
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
|
// check for partitioning objects on the y-axis
|
||||||
int result = comparePartitioned(Y_AXIS, da, db);
|
int result = comparePartitioned(Y_AXIS, da, db);
|
||||||
if (result != 0) {
|
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;
|
// otherwise use a consistent ordering for non-overlappers;
|
||||||
// see narya/docs/miso/render_sort_diagram.png for more info
|
// 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;
|
return 1;
|
||||||
} else if (da.ry > db.oy) {
|
} else if (db.lx >= da.lx && db.ry >= da.ry) {
|
||||||
return (db.lx > da.ox) ? -1 : 1;
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,6 +684,9 @@ public class DirtyItemList
|
|||||||
/** The list of dirty items sorted by y-position. */
|
/** The list of dirty items sorted by y-position. */
|
||||||
protected SortableArrayList _yitems = new SortableArrayList();
|
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. */
|
/** The render comparator we'll use for our final, magical sort. */
|
||||||
protected Comparator _rcomp = new RenderComparator();
|
protected Comparator _rcomp = new RenderComparator();
|
||||||
|
|
||||||
@@ -659,4 +722,13 @@ public class DirtyItemList
|
|||||||
* y-coordinate order. */
|
* y-coordinate order. */
|
||||||
protected static final Comparator ORIGIN_Y_COMP =
|
protected static final Comparator ORIGIN_Y_COMP =
|
||||||
new OriginComparator(Y_AXIS);
|
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());
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user