/* ============ idPush::ClipPush Try to push other entities by moving the given entity. ============ */ float idPush::ClipPush( trace_t &results, idEntity *pusher, const int flags, const idVec3 &oldOrigin, const idMat3 &oldAxis, idVec3 &newOrigin, idMat3 &newAxis ) { idVec3 translation; idRotation rotation; float mass; mass = 0.0f; results.fraction = 1.0f; results.endpos = newOrigin; results.endAxis = newAxis; memset( &results.c, 0, sizeof( results.c ) ); // translational push translation = newOrigin - oldOrigin; // if the pusher translates if ( translation != vec3_origin ) { mass += ClipTranslationalPush( results, pusher, flags, newOrigin, translation ); if ( results.fraction < 1.0f ) { newOrigin = oldOrigin; newAxis = oldAxis; return mass; } } else { newOrigin = oldOrigin; } // rotational push rotation = ( oldAxis.Transpose() * newAxis ).ToRotation(); rotation.SetOrigin( newOrigin ); rotation.Normalize180(); rotation.ReCalculateMatrix(); // recalculate the rotation matrix to avoid accumulating rounding errors // if the pusher rotates if ( rotation.GetAngle() != 0.0f ) { // recalculate new axis to avoid floating point rounding problems newAxis = oldAxis * rotation.ToMat3(); newAxis.OrthoNormalizeSelf(); newAxis.FixDenormals(); newAxis.FixDegeneracies(); pusher->GetPhysics()->GetClipModel()->SetPosition( newOrigin, oldAxis ); mass += ClipRotationalPush( results, pusher, flags, newAxis, rotation ); if ( results.fraction < 1.0f ) { newOrigin = oldOrigin; newAxis = oldAxis; return mass; } } else { newAxis = oldAxis; } return mass; }