Skip to content
This repository was archived by the owner on Jan 5, 2024. It is now read-only.

Commit 631078f

Browse files
committed
Fix atoms missing from terrain hit list
1 parent 5cd6977 commit 631078f

File tree

1 file changed

+43
-38
lines changed

1 file changed

+43
-38
lines changed

Entities/AtomGroup.cpp

Lines changed: 43 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,40 +1220,43 @@ float AtomGroup::Travel(Vector &position,
12201220
{
12211221
somethingPenetrated = false;
12221222

1223-
distMass = mass / static_cast<float>(hitTerrAtoms.size() * (m_Resolution ? m_Resolution : 1));
1224-
distMI = m_MomInertia / static_cast<float>(hitTerrAtoms.size() * (m_Resolution ? m_Resolution : 1));
1223+
distMass = mass / static_cast<float>((hitTerrAtoms.size() - penetratingAtoms.size()) * (m_Resolution ? m_Resolution : 1));
1224+
distMI = m_MomInertia / static_cast<float>((hitTerrAtoms.size() - penetratingAtoms.size()) * (m_Resolution ? m_Resolution : 1));
12251225

12261226
for (std::list<Atom*>::iterator aItr = hitTerrAtoms.begin(); aItr != hitTerrAtoms.end(); )
12271227
{
1228-
// Calc and store the accurate hit radius of the Atom in relation to the CoM
1229-
tempVec = (*aItr)->GetOffset().GetXFlipped(hFlipped);
1230-
hitData.HitRadius[HITOR] = tempVec.RadRotate(rotation.GetRadAngle()) *= c_MPP;
1231-
// Figure out the pre-collision velocity of the hitting atom due to body translation and rotation.
1232-
hitData.HitVel[HITOR] = velocity + tempVec.Perpendicularize() * angVel;
1233-
1234-
radMag = hitData.HitRadius[HITOR].GetMagnitude();
1235-
// These are set temporarily here, will be re-set later when the normal of the hit terrain bitmap (ortho pixel side) is known.
1236-
hitData.HitDenominator = (1.0F / distMass) + ((radMag * radMag) / distMI);
1237-
hitData.PreImpulse[HITOR] = hitData.HitVel[HITOR] / hitData.HitDenominator;
1238-
// Set the atom with the hit data with all the info we have so far.
1239-
(*aItr)->SetHitData(hitData);
1240-
1241-
if (g_SceneMan.WillPenetrate((*aItr)->GetCurrentPos().GetFloorIntX(), (*aItr)->GetCurrentPos().GetFloorIntY(), hitData.PreImpulse[HITOR]))
1242-
{
1243-
// Move the penetrating atom to the pen. list from the coll. list.
1244-
penetratingAtoms.push_back(*aItr);
1245-
aItr = hitTerrAtoms.erase(aItr);
1246-
somethingPenetrated = true;
1228+
const std::list<Atom *>::iterator duplicateAtomItr = std::find(penetratingAtoms.begin(), penetratingAtoms.end(), *aItr);
1229+
if (duplicateAtomItr == penetratingAtoms.end()) {
1230+
// Calc and store the accurate hit radius of the Atom in relation to the CoM
1231+
tempVec = (*aItr)->GetOffset().GetXFlipped(hFlipped);
1232+
hitData.HitRadius[HITOR] = tempVec.RadRotate(rotation.GetRadAngle()) *= c_MPP;
1233+
// Figure out the pre-collision velocity of the hitting atom due to body translation and rotation.
1234+
hitData.HitVel[HITOR] = velocity + tempVec.Perpendicularize() * angVel;
1235+
1236+
radMag = hitData.HitRadius[HITOR].GetMagnitude();
1237+
// These are set temporarily here, will be re-set later when the normal of the hit terrain bitmap (ortho pixel side) is known.
1238+
hitData.HitDenominator = (1.0F / distMass) + ((radMag * radMag) / distMI);
1239+
hitData.PreImpulse[HITOR] = hitData.HitVel[HITOR] / hitData.HitDenominator;
1240+
// Set the atom with the hit data with all the info we have so far.
1241+
(*aItr)->SetHitData(hitData);
1242+
1243+
if (g_SceneMan.WillPenetrate((*aItr)->GetCurrentPos().GetFloorIntX(), (*aItr)->GetCurrentPos().GetFloorIntY(), hitData.PreImpulse[HITOR]))
1244+
{
1245+
// Move the penetrating atom to the pen. list from the coll. list.
1246+
penetratingAtoms.push_back(*aItr);
1247+
somethingPenetrated = true;
1248+
} else
1249+
++aItr;
12471250
} else
12481251
++aItr;
12491252
}
12501253
}
1251-
while (!hitTerrAtoms.empty() && somethingPenetrated);
1254+
while (somethingPenetrated);
12521255

12531256
// TERRAIN BOUNCE //////////////////////////////////////////////////////////////////
12541257
// If some Atoms could not penetrate even though all the impulse was on them,
12551258
// gather the bounce results and apply them to the owner.
1256-
if (!hitTerrAtoms.empty())
1259+
if (hitTerrAtoms.size() != penetratingAtoms.size())
12571260
{
12581261
newDir = true;
12591262

@@ -1943,29 +1946,31 @@ before adding them to the MovableMan.
19431946
do {
19441947
somethingPenetrated = false;
19451948

1946-
massDist = mass / static_cast<float>(hitTerrAtoms.size() * (m_Resolution ? m_Resolution : 1));
1949+
massDist = mass / static_cast<float>((hitTerrAtoms.size() - penetratingAtoms.size()) * (m_Resolution ? m_Resolution : 1));
19471950

19481951
for (deque<pair<Atom *, Vector> >::iterator aoItr = hitTerrAtoms.begin(); aoItr != hitTerrAtoms.end(); )
19491952
{
1950-
if (g_SceneMan.WillPenetrate(intPos[X] + (*aoItr).second.GetFloorIntX(),
1951-
intPos[Y] + (*aoItr).second.GetFloorIntY(),
1952-
forceVel,
1953-
massDist))
1954-
{
1955-
// Move the penetrating atom to the pen. list from the coll. list.
1956-
penetratingAtoms.push_back(pair<Atom *, Vector>((*aoItr).first, (*aoItr).second));
1957-
aoItr = hitTerrAtoms.erase(aoItr);
1958-
somethingPenetrated = true;
1959-
}
1960-
else
1961-
++aoItr;
1953+
const deque<pair<Atom *, Vector> >::iterator duplicateAtomItr = std::find(penetratingAtoms.begin(), penetratingAtoms.end(), *aoItr);
1954+
if (duplicateAtomItr == penetratingAtoms.end()) {
1955+
if (g_SceneMan.WillPenetrate(intPos[X] + (*aoItr).second.GetFloorIntX(),
1956+
intPos[Y] + (*aoItr).second.GetFloorIntY(),
1957+
forceVel,
1958+
massDist))
1959+
{
1960+
// Move the penetrating atom to the pen. list from the coll. list.
1961+
penetratingAtoms.push_back(pair<Atom *, Vector>((*aoItr).first, (*aoItr).second));
1962+
somethingPenetrated = true;
1963+
} else
1964+
++aoItr;
1965+
} else
1966+
++aoItr;
19621967
}
1963-
} while (!hitTerrAtoms.empty() && somethingPenetrated);
1968+
} while (somethingPenetrated);
19641969

19651970
// TERRAIN BOUNCE //////////////////////////////////////////////////////////////////
19661971
// If some Atom:s could not penetrate even though all the mass was on them,
19671972
// gather the bounce results and apply them to the owner.
1968-
if (!hitTerrAtoms.empty())
1973+
if (hitTerrAtoms.size() != penetratingAtoms.size())
19691974
{
19701975
newDir = true;
19711976
prevError = error;

0 commit comments

Comments
 (0)