fix(model): correct binary search logic in CM2Model::FindKey

This commit is contained in:
fallenoak 2025-11-01 23:32:03 -05:00
parent 42c6e68977
commit 4db31eced1
No known key found for this signature in database
GPG Key ID: 7628F8E61AEA070D

View File

@ -842,14 +842,15 @@ void CM2Model::DetachFromScene() {
void CM2Model::FindKey(M2ModelBoneSeq* sequence, const M2TrackBase& track, uint32_t& currentKey, uint32_t& nextKey, float& ratio) { void CM2Model::FindKey(M2ModelBoneSeq* sequence, const M2TrackBase& track, uint32_t& currentKey, uint32_t& nextKey, float& ratio) {
if (!track.sequenceTimes.Count()) { if (!track.sequenceTimes.Count()) {
nextKey = 0;
currentKey = 0; currentKey = 0;
nextKey = 0;
ratio = 0.0f; ratio = 0.0f;
return; return;
} }
uint32_t sequenceDuration = sequence->uint0; uint32_t sequenceTime = sequence->uint0;
uint32_t sequenceIndex = sequence->uint4; uint32_t sequenceIndex = sequence->uint4;
if (track.loopIndex == 0xFFFF) { if (track.loopIndex == 0xFFFF) {
@ -857,7 +858,7 @@ void CM2Model::FindKey(M2ModelBoneSeq* sequence, const M2TrackBase& track, uint3
sequenceIndex = 0; sequenceIndex = 0;
} }
} else { } else {
sequenceDuration = this->m_loops[track.loopIndex]; sequenceTime = this->m_loops[track.loopIndex];
sequenceIndex = 0; sequenceIndex = 0;
} }
@ -866,8 +867,9 @@ void CM2Model::FindKey(M2ModelBoneSeq* sequence, const M2TrackBase& track, uint3
auto keyTimes = sequenceTimes.times.Data(); auto keyTimes = sequenceTimes.times.Data();
if (numKeys <= 1) { if (numKeys <= 1) {
nextKey = 0;
currentKey = 0; currentKey = 0;
nextKey = 0;
ratio = 0.0f; ratio = 0.0f;
return; return;
@ -878,34 +880,43 @@ void CM2Model::FindKey(M2ModelBoneSeq* sequence, const M2TrackBase& track, uint3
} }
uint32_t v15 = currentKey; uint32_t v15 = currentKey;
auto v16 = sequenceDuration - keyTimes[currentKey]; auto v16 = sequenceTime - keyTimes[currentKey];
if (v16 >= 500) { if (v16 >= 500) {
if (v16 < 0xFFFFFE0C) { if (v16 < 0xFFFFFE0C) {
v15 = 0; if (sequenceTime >= 500) {
// Run binary search for key containing sequence time
if (sequenceDuration >= 500) { int32_t lowKey = 0;
uint32_t v20 = numKeys; int32_t highKey = numKeys;
do { while (lowKey < highKey) {
uint32_t v21 = (v20 + v15) >> 1; int32_t midKey = (lowKey + highKey) / 2;
if (sequenceDuration >= keyTimes[v21]) { if (midKey + 1 >= numKeys) {
v15 = v21 + 1; lowKey = midKey;
break;
if (v21 + 1 >= numKeys || sequenceDuration < keyTimes[v21 + 1]) {
v15 = v21;
break;
}
} else {
v20 = v21 - 1;
} }
} while (v15 < v20);
if (sequenceTime >= keyTimes[midKey] && sequenceTime < keyTimes[midKey + 1]) {
lowKey = midKey;
break;
}
if (sequenceTime >= keyTimes[midKey]) {
lowKey = midKey + 1;
} else {
highKey = midKey - 1;
}
}
v15 = lowKey;
} else { } else {
v15 = 0;
uint32_t* v19 = keyTimes + 1; uint32_t* v19 = keyTimes + 1;
do { do {
if (*v19 > sequenceDuration) { if (*v19 > sequenceTime) {
break; break;
} }
@ -917,7 +928,7 @@ void CM2Model::FindKey(M2ModelBoneSeq* sequence, const M2TrackBase& track, uint3
uint32_t* v18 = &keyTimes[v15]; uint32_t* v18 = &keyTimes[v15];
do { do {
if (*v18 <= sequenceDuration) { if (*v18 <= sequenceTime) {
break; break;
} }
@ -929,7 +940,7 @@ void CM2Model::FindKey(M2ModelBoneSeq* sequence, const M2TrackBase& track, uint3
uint32_t* v17 = &keyTimes[v15 + 1]; uint32_t* v17 = &keyTimes[v15 + 1];
do { do {
if (*v17 > sequenceDuration) { if (*v17 > sequenceTime) {
break; break;
} }
@ -939,8 +950,9 @@ void CM2Model::FindKey(M2ModelBoneSeq* sequence, const M2TrackBase& track, uint3
} }
if (v15 + 1 >= numKeys) { if (v15 + 1 >= numKeys) {
nextKey = v15;
currentKey = v15; currentKey = v15;
nextKey = v15;
ratio = 0.0f; ratio = 0.0f;
} else { } else {
currentKey = v15; currentKey = v15;
@ -949,7 +961,7 @@ void CM2Model::FindKey(M2ModelBoneSeq* sequence, const M2TrackBase& track, uint3
auto currentKeyTime = keyTimes[currentKey]; auto currentKeyTime = keyTimes[currentKey];
auto nextKeyTime = keyTimes[nextKey]; auto nextKeyTime = keyTimes[nextKey];
ratio = static_cast<float>(sequenceDuration - currentKeyTime) / static_cast<float>(nextKeyTime - currentKeyTime); ratio = static_cast<float>(sequenceTime - currentKeyTime) / static_cast<float>(nextKeyTime - currentKeyTime);
} }
} }