You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
80 lines
3.0 KiB
C
80 lines
3.0 KiB
C
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
|
|
|
#ifndef CRYINCLUDE_TOOLS_RC_RESOURCECOMPILERPC_ADJUSTROTLOG_H
|
|
#define CRYINCLUDE_TOOLS_RC_RESOURCECOMPILERPC_ADJUSTROTLOG_H
|
|
#pragma once
|
|
|
|
|
|
inline double DLength (const Vec3& v)
|
|
{
|
|
return sqrt (double(v.x) * double(v.x) + double(v.y) * double(v.y) + double(v.z) * double(v.z));
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Given the rotations in logarithmic space, adjusts the target rotation so
|
|
// that it's the same in rotational group, but the closest to the reference
|
|
// in the QLog space.
|
|
inline void AdjustRotLog (Vec3& vTgt, const Vec3& vRef)
|
|
{
|
|
double dLenTgt = DLength(vTgt);
|
|
const double dPi = 3.1415926535897932384626433832795;
|
|
if (dLenTgt < 1e-4)
|
|
{
|
|
// the target is very small rotation, so the algorithm is to find
|
|
// ANY vector of length n*PI closest to the vRef point
|
|
double dLenRef = DLength(vRef);
|
|
if (dLenRef > dPi / 2) // Otherwise the vRef vector is small enough not to make any adjustments
|
|
{
|
|
double f = (dPi * floor(dLenRef / dPi + 0.5) / dLenRef);
|
|
vTgt.x = float(vRef.x * f);
|
|
vTgt.y = float(vRef.y * f);
|
|
vTgt.z = float(vRef.z * f);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// the target is big enough rotation to pick the rotation axis out
|
|
|
|
// find the projection of the reference to the target axis
|
|
// then find the target (projection) mod PI
|
|
// there are basically three possibilities: the new target is in the same PI interval
|
|
// as the reference projection, in the next or in the previous. Find the closest.
|
|
|
|
double dProjRef = (vRef * vTgt) / dLenTgt;
|
|
double dModTgt = fmod (dLenTgt, dPi);
|
|
if (dModTgt < 0)
|
|
{
|
|
dModTgt += dPi;
|
|
}
|
|
assert (dModTgt >= 0 && dModTgt < dPi);
|
|
|
|
double dBaseTgt = dPi * floor (dProjRef / dPi + 0.5);
|
|
|
|
double dNewTgtR = dBaseTgt + dModTgt;
|
|
double dNewTgtL = dBaseTgt + dModTgt - dPi;
|
|
double dNewTgt = (fabs(dNewTgtR - dProjRef) < fabs(dNewTgtL - dProjRef))
|
|
? dNewTgtR : dNewTgtL;
|
|
|
|
assert (fabs(dNewTgt + dPi - dProjRef) > fabs(dNewTgt - dProjRef));
|
|
assert (fabs(dNewTgt - dPi - dProjRef) > fabs(dNewTgt - dProjRef));
|
|
|
|
double f = (dNewTgt / dLenTgt);
|
|
vTgt.x = float(vTgt.x * f);
|
|
vTgt.y = float(vTgt.y * f);
|
|
vTgt.z = float(vTgt.z * f);
|
|
}
|
|
}
|
|
|
|
#endif // CRYINCLUDE_TOOLS_RC_RESOURCECOMPILERPC_ADJUSTROTLOG_H
|