mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-10 04:36:57 +08:00
Use linear search to find keys.
Linear consistently outperforms binary using a wide sampling of real world data.
This commit is contained in:
parent
62e17f7a65
commit
34ad58febe
@ -114,8 +114,36 @@ public class Animation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Binary search using a stride of 1.
|
/** Binary search using a stride of 1.
|
||||||
* @return The index of the first value <= to the target, else the first value if none. */
|
* @param target >= the first value.
|
||||||
static int binarySearch (float[] values, float target) {
|
* @return The index of the first value <= to the target. */
|
||||||
|
static int search (float[] values, float target) {
|
||||||
|
int n = values.length;
|
||||||
|
for (int i = 1; i < n; i++)
|
||||||
|
if (values[i] > target) return i - 1;
|
||||||
|
return n - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Binary search using a stride of 2.
|
||||||
|
* @param target >= the first value and < the last value.
|
||||||
|
* @return The index / 2 of the first value <= to the target. */
|
||||||
|
static int search2 (float[] values, float target) {
|
||||||
|
int last = values.length - 4;
|
||||||
|
for (int i = 2; i <= last; i += 2)
|
||||||
|
if (values[i] > target) return (i >> 1) - 1;
|
||||||
|
return last >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Binary search using the specified stride.
|
||||||
|
* @param target >= the first and < the last value.
|
||||||
|
* @return The index / step of the first value <= to the target. */
|
||||||
|
static int searchN (float[] values, float target, int step) {
|
||||||
|
int last = values.length - (step << 1);
|
||||||
|
for (int i = step; i <= last; i += step)
|
||||||
|
if (values[i] > target) return i / step - 1;
|
||||||
|
return last / step;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int search_binary (float[] values, float target) {
|
||||||
int low = 0, high = values.length - 1, current;
|
int low = 0, high = values.length - 1, current;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (low == high) return low;
|
if (low == high) return low;
|
||||||
@ -127,10 +155,7 @@ public class Animation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Binary search using a stride of 2.
|
static int search2_binary (float[] values, float target) {
|
||||||
* @param target >= the first and < the last value.
|
|
||||||
* @return The index / 2 of the first value <= to the target. */
|
|
||||||
static int binarySearch2 (float[] values, float target) {
|
|
||||||
int low = 0, high = (values.length >> 1) - 2, current;
|
int low = 0, high = (values.length >> 1) - 2, current;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (low == high) return low;
|
if (low == high) return low;
|
||||||
@ -142,13 +167,10 @@ public class Animation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Binary search using the specified stride.
|
static int searchN_binary (float[] values, float target, int step) {
|
||||||
* @param target >= the first and < the last value.
|
|
||||||
* @return The index / 2 of the first value <= to the target. */
|
|
||||||
static int binarySearch (float[] values, float target, int step) {
|
|
||||||
int low = 0, high = values.length / step - 2, current;
|
int low = 0, high = values.length / step - 2, current;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (low == high) return low;
|
if (low >= high) return low;
|
||||||
current = ((low + high) >>> 1) + 1;
|
current = ((low + high) >>> 1) + 1;
|
||||||
if (values[current * step] <= target)
|
if (values[current * step] <= target)
|
||||||
low = current;
|
low = current;
|
||||||
@ -157,15 +179,6 @@ public class Animation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Linear search using the specified stride. Not used, but for comparison with binary searches.
|
|
||||||
* @param target >= the first and < the last value.
|
|
||||||
* @return The index / 2 of the first value <= to the target. */
|
|
||||||
static int linearSearch (float[] values, float target, int step) {
|
|
||||||
for (int i = 0, last = values.length - 1; i < last; i += step)
|
|
||||||
if (values[i] > target) return i / step - 1;
|
|
||||||
return step;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Controls how a timeline value is mixed with the setup pose value or current pose value when a timeline's <code>alpha</code>
|
/** Controls how a timeline value is mixed with the setup pose value or current pose value when a timeline's <code>alpha</code>
|
||||||
* < 1.
|
* < 1.
|
||||||
* <p>
|
* <p>
|
||||||
@ -202,7 +215,7 @@ public class Animation {
|
|||||||
in, out
|
in, out
|
||||||
}
|
}
|
||||||
|
|
||||||
static private enum Property {
|
static enum Property {
|
||||||
rotate, translateX, translateY, scaleX, scaleY, shearX, shearY, //
|
rotate, translateX, translateY, scaleX, scaleY, shearX, shearY, //
|
||||||
rgb, a, rgb2, //
|
rgb, a, rgb2, //
|
||||||
attachment, deform, //
|
attachment, deform, //
|
||||||
@ -466,7 +479,7 @@ public class Animation {
|
|||||||
public float getCurveValue (float time) {
|
public float getCurveValue (float time) {
|
||||||
float[] frames = this.frames;
|
float[] frames = this.frames;
|
||||||
if (time >= frames[frames.length - ENTRIES]) return frames[frames.length - 1];
|
if (time >= frames[frames.length - ENTRIES]) return frames[frames.length - 1];
|
||||||
int frameIndex = binarySearch2(frames, time);
|
int frameIndex = search2(frames, time);
|
||||||
float[] curves = this.curves;
|
float[] curves = this.curves;
|
||||||
int i = (int)curves[frameIndex];
|
int i = (int)curves[frameIndex];
|
||||||
if (i < BEZIER) {
|
if (i < BEZIER) {
|
||||||
@ -578,7 +591,7 @@ public class Animation {
|
|||||||
x = frames[frames.length - ENTRIES + VALUE1];
|
x = frames[frames.length - ENTRIES + VALUE1];
|
||||||
y = frames[frames.length - ENTRIES + VALUE2];
|
y = frames[frames.length - ENTRIES + VALUE2];
|
||||||
} else {
|
} else {
|
||||||
int frameIndex = binarySearch(frames, time, ENTRIES), frame = frameIndex * ENTRIES;
|
int frameIndex = searchN(frames, time, ENTRIES), frame = frameIndex * ENTRIES;
|
||||||
float percent = getCurvePercent(frameIndex, time, frame, ENTRIES);
|
float percent = getCurvePercent(frameIndex, time, frame, ENTRIES);
|
||||||
x = frames[frame + VALUE1];
|
x = frames[frame + VALUE1];
|
||||||
y = frames[frame + VALUE2];
|
y = frames[frame + VALUE2];
|
||||||
@ -641,7 +654,7 @@ public class Animation {
|
|||||||
x = frames[frames.length - ENTRIES + VALUE1] * bone.data.scaleX;
|
x = frames[frames.length - ENTRIES + VALUE1] * bone.data.scaleX;
|
||||||
y = frames[frames.length - ENTRIES + VALUE2] * bone.data.scaleY;
|
y = frames[frames.length - ENTRIES + VALUE2] * bone.data.scaleY;
|
||||||
} else {
|
} else {
|
||||||
int frameIndex = binarySearch(frames, time, ENTRIES), frame = frameIndex * ENTRIES;
|
int frameIndex = searchN(frames, time, ENTRIES), frame = frameIndex * ENTRIES;
|
||||||
float percent = getCurvePercent(frameIndex, time, frame, ENTRIES);
|
float percent = getCurvePercent(frameIndex, time, frame, ENTRIES);
|
||||||
x = frames[frame + VALUE1];
|
x = frames[frame + VALUE1];
|
||||||
y = frames[frame + VALUE2];
|
y = frames[frame + VALUE2];
|
||||||
@ -745,7 +758,7 @@ public class Animation {
|
|||||||
x = frames[frames.length - ENTRIES + VALUE1] * bone.data.scaleX;
|
x = frames[frames.length - ENTRIES + VALUE1] * bone.data.scaleX;
|
||||||
y = frames[frames.length - ENTRIES + VALUE2] * bone.data.scaleY;
|
y = frames[frames.length - ENTRIES + VALUE2] * bone.data.scaleY;
|
||||||
} else {
|
} else {
|
||||||
int frameIndex = binarySearch(frames, time, ENTRIES), frame = frameIndex * ENTRIES;
|
int frameIndex = searchN(frames, time, ENTRIES), frame = frameIndex * ENTRIES;
|
||||||
float percent = getCurvePercent(frameIndex, time, frame, ENTRIES);
|
float percent = getCurvePercent(frameIndex, time, frame, ENTRIES);
|
||||||
x = frames[frame + VALUE1];
|
x = frames[frame + VALUE1];
|
||||||
y = frames[frame + VALUE2];
|
y = frames[frame + VALUE2];
|
||||||
@ -829,7 +842,7 @@ public class Animation {
|
|||||||
b = frames[i + B];
|
b = frames[i + B];
|
||||||
a = frames[i + A];
|
a = frames[i + A];
|
||||||
} else {
|
} else {
|
||||||
int frameIndex = binarySearch(frames, time, ENTRIES), frame = frameIndex * ENTRIES;
|
int frameIndex = searchN(frames, time, ENTRIES), frame = frameIndex * ENTRIES;
|
||||||
float percent = getCurvePercent(frameIndex, time, frame, ENTRIES);
|
float percent = getCurvePercent(frameIndex, time, frame, ENTRIES);
|
||||||
r = frames[frame + R];
|
r = frames[frame + R];
|
||||||
g = frames[frame + G];
|
g = frames[frame + G];
|
||||||
@ -921,7 +934,7 @@ public class Animation {
|
|||||||
g2 = frames[i + G2];
|
g2 = frames[i + G2];
|
||||||
b2 = frames[i + B2];
|
b2 = frames[i + B2];
|
||||||
} else {
|
} else {
|
||||||
int frameIndex = binarySearch(frames, time, ENTRIES), frame = frameIndex * ENTRIES;
|
int frameIndex = searchN(frames, time, ENTRIES), frame = frameIndex * ENTRIES;
|
||||||
float percent = getCurvePercent(frameIndex, time, frame, ENTRIES);
|
float percent = getCurvePercent(frameIndex, time, frame, ENTRIES);
|
||||||
r = frames[frame + R];
|
r = frames[frame + R];
|
||||||
g = frames[frame + G];
|
g = frames[frame + G];
|
||||||
@ -1003,7 +1016,7 @@ public class Animation {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String attachmentName = attachmentNames[binarySearch(frames, time)];
|
String attachmentName = attachmentNames[search(frames, time)];
|
||||||
slot.setAttachment(attachmentName == null ? null : skeleton.getAttachment(slotIndex, attachmentName));
|
slot.setAttachment(attachmentName == null ? null : skeleton.getAttachment(slotIndex, attachmentName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1151,7 +1164,7 @@ public class Animation {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int frame = binarySearch(frames, time);
|
int frame = search(frames, time);
|
||||||
float percent = getCurvePercent(frame, time, frame, 1);
|
float percent = getCurvePercent(frame, time, frame, 1);
|
||||||
float[] prevVertices = frameVertices[frame];
|
float[] prevVertices = frameVertices[frame];
|
||||||
float[] nextVertices = frameVertices[frame + 1];
|
float[] nextVertices = frameVertices[frame + 1];
|
||||||
@ -1272,7 +1285,7 @@ public class Animation {
|
|||||||
if (lastTime < frames[0])
|
if (lastTime < frames[0])
|
||||||
frame = 0;
|
frame = 0;
|
||||||
else {
|
else {
|
||||||
frame = binarySearch(frames, lastTime) + 1;
|
frame = search(frames, lastTime) + 1;
|
||||||
float frameTime = frames[frame];
|
float frameTime = frames[frame];
|
||||||
while (frame > 0) { // Fire multiple events with the same frame.
|
while (frame > 0) { // Fire multiple events with the same frame.
|
||||||
if (frames[frame - 1] != frameTime) break;
|
if (frames[frame - 1] != frameTime) break;
|
||||||
@ -1326,7 +1339,7 @@ public class Animation {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int[] drawOrderToSetupIndex = drawOrders[binarySearch(frames, time)];
|
int[] drawOrderToSetupIndex = drawOrders[search(frames, time)];
|
||||||
if (drawOrderToSetupIndex == null)
|
if (drawOrderToSetupIndex == null)
|
||||||
arraycopy(slots.items, 0, drawOrder.items, 0, slots.size);
|
arraycopy(slots.items, 0, drawOrder.items, 0, slots.size);
|
||||||
else {
|
else {
|
||||||
@ -1422,7 +1435,7 @@ public class Animation {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int frameIndex = binarySearch(frames, time, ENTRIES), frame = frameIndex * ENTRIES;
|
int frameIndex = searchN(frames, time, ENTRIES), frame = frameIndex * ENTRIES;
|
||||||
float percent = getCurvePercent(frameIndex, time, frame, ENTRIES);
|
float percent = getCurvePercent(frameIndex, time, frame, ENTRIES);
|
||||||
float mix = frames[frame + MIX];
|
float mix = frames[frame + MIX];
|
||||||
float softness = frames[frame + SOFTNESS];
|
float softness = frames[frame + SOFTNESS];
|
||||||
@ -1519,7 +1532,7 @@ public class Animation {
|
|||||||
scale = frames[i + SCALE];
|
scale = frames[i + SCALE];
|
||||||
shear = frames[i + SHEAR];
|
shear = frames[i + SHEAR];
|
||||||
} else {
|
} else {
|
||||||
int frameIndex = binarySearch(frames, time, ENTRIES), frame = frameIndex * ENTRIES;
|
int frameIndex = searchN(frames, time, ENTRIES), frame = frameIndex * ENTRIES;
|
||||||
float percent = getCurvePercent(frameIndex, time, frame, ENTRIES);
|
float percent = getCurvePercent(frameIndex, time, frame, ENTRIES);
|
||||||
rotate = frames[frame + ROTATE];
|
rotate = frames[frame + ROTATE];
|
||||||
translate = frames[frame + TRANSLATE];
|
translate = frames[frame + TRANSLATE];
|
||||||
@ -1662,7 +1675,7 @@ public class Animation {
|
|||||||
rotate = frames[frames.length - ENTRIES + VALUE1];
|
rotate = frames[frames.length - ENTRIES + VALUE1];
|
||||||
translate = frames[frames.length - ENTRIES + VALUE2];
|
translate = frames[frames.length - ENTRIES + VALUE2];
|
||||||
} else {
|
} else {
|
||||||
int frameIndex = binarySearch(frames, time, ENTRIES), frame = frameIndex * ENTRIES;
|
int frameIndex = searchN(frames, time, ENTRIES), frame = frameIndex * ENTRIES;
|
||||||
float percent = getCurvePercent(frameIndex, time, frame, ENTRIES);
|
float percent = getCurvePercent(frameIndex, time, frame, ENTRIES);
|
||||||
rotate = frames[frame + VALUE1];
|
rotate = frames[frame + VALUE1];
|
||||||
translate = frames[frame + VALUE2];
|
translate = frames[frame + VALUE2];
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user