取多个Vector3的平均值

时间:2019-02-26 09:07:08

标签: c# unity3d

因此,我正在使用像kinect一样的深度相机。 (不是kinect)。后面还有Nuitrack,用于骨骼跟踪。但是,它为播放器返回的位置不稳定。当静止不动时,它返回的数字最多可以增加或减少10。

示例:用户保持静止不动,数据在第一帧返回位置100,下一帧返回102,然后是97,然后再次返回100,然后是106,等等。它在更新中返回这些位置我们用它来移动图像。 (因此,用户可以控制图像)但是由于数据不一致,您可能希望此图像的移动非常不稳定。根据Nuitrack的说法,这是正确的,用户本身需要为此找到解决方案。 enter image description here

我尝试从一个位置拉到另一个位置,但这使它感觉不那么互动,因为一旦我到达了拉绳实际上很平滑的位置,就会有很大的延迟。我还尝试仅使用新的位置数据,如果它与nuitrack给我的先前位置不同,比如说4个像素,则效果更好一些,但即使我也套牢,也会导致图像跳动。使用此功能:

foreach (User user in frame.Users)
        {
            if (Vector3.Distance(_lastPos, user.Proj.ToVector3()) >4f)
            {
                Vector3 final = ((_lastPos + user.Proj.ToVector3()) /2);
                userData.Add(new UserData(user.ID, user.Real.ToVector3(), final));
                _lastPos = user.Proj.ToVector3();
            }
            else
            {
                userData.Add(new UserData(user.ID, user.Real.ToVector3(), _lastPos));
            }

以及lerp函数:

float _userX = user.ProjPosition.x * (_cameraPos.x *2)- _cameraPos.x;
            Vector3 _newPos = new Vector3(_userX, _basketPos.y, _basketPos.z);
            _basketPrefab.transform.position = Vector3.Lerp(_basketPrefab.transform.position, _newPos, Time.deltaTime * 30f);

编辑:还有其他人吗?

1 个答案:

答案 0 :(得分:1)

您可以尝试保留最近n个位置的列表,然后使用0.5f(半值)作为t将它们合在一起来计算这些位置的平均值。然后,您可以通过再次相互套住先前固定的位置来增加“平滑度”的级别,从而使其在每次迭代时更加平滑。但是,每次迭代都会使它感觉更加缓慢,并且需要在平滑和响应之间找到平衡。

(未经测试的示例)。

List<Quaternion> lastPosition = new List<Quaternion>(); //Keep a list of the last positions
int smoothing = 16; //Max amount of smoothing, higher means more positions will be used for the smoothness
enum SmoothingLevels { None, Mild, Moderate, Severe, Extreme } //Level of smoothness you want to use
SmoothingLevels smoothingLevel;
Vector3 pos;

//remove the oldest entry from the list 
if(lastPosition.Count > 0)
{
    lastPosition.RemoveAt(0);
}

//Add the newest data to the list
while (lastPosition.Count < smoothing)
{
    lastPosition.Add(transform.position);
}

Vector3 vecA = lastPosition[0];
Vector3 vecB = lastPosition[1];
Vector3 vecC = lastPosition[2];
Vector3 vecD = lastPosition[3];
Vector3 vecE = lastPosition[4];
Vector3 vecF = lastPosition[5];
Vector3 vecG = lastPosition[6];
Vector3 vecH = lastPosition[7];
Vector3 vecI = lastPosition[8];
Vector3 vecJ = lastPosition[9];
Vector3 vecK = lastPosition[10];
Vector3 vecL = lastPosition[11];
Vector3 vecM = lastPosition[12];
Vector3 vecN = lastPosition[13];
Vector3 vecO = lastPosition[14];
Vector3 vecP = lastPosition[15];

//Lerp each subsequent position by t 0.5 to get the average position of the two.
//This is the base smoothing, where smoothing is low and responsiveness is high
Vector3 vecAB = Vector3.Lerp(vecA, vecB, 0.5f);
Vector3 vecCD = Vector3.Lerp(vecC, vecD, 0.5f);
Vector3 vecEF = Vector3.Lerp(vecE, vecF, 0.5f);
Vector3 vecGH = Vector3.Lerp(vecG, vecH, 0.5f);
Vector3 vecIJ = Vector3.Lerp(vecI, vecJ, 0.5f);
Vector3 vecKL = Vector3.Lerp(vecK, vecL, 0.5f);
Vector3 vecMN = Vector3.Lerp(vecM, vecN, 0.5f);
Vector3 vecOP = Vector3.Lerp(vecO, vecP, 0.5f);

//moderate smoothing, Lerp the previously lerped position again with each other to increase the smoothness
Vector3 vecABCD = Vector3.Lerp(vecAB, vecCD, 0.5f);
Vector3 vecEFGH = Vector3.Lerp(vecEF, vecGH, 0.5f);
Vector3 vecIJKL = Vector3.Lerp(vecIJ, vecKL, 0.5f);
Vector3 vecMNOP = Vector3.Lerp(vecMN, vecOP, 0.5f);

//Severe smoothing, High smoothness, lower responsiveness
Vector3 vecABCDEFGH = Vector3.Lerp(vecABCD, vecEFGH, 0.5f);
Vector3 vecIJKLMNOP = Vector3.Lerp(vecIJKL, vecMNOP, 0.5f);

//Extreme smoothing, this will take the average of all 16 positions. Very smooth, feels really sluggish
Vector3 vecABCDEFGHIJKLMNOP = Vector3.Lerp(vecABCDEFGH, vecIJKLMNOP, 0.5f);
switch (smoothingLevel)
{
    case SmoothingLevels.None:
        pos = transform.position;
        break;
    case SmoothingLevels.Mild:
        pos = vecOP;
        break;
    case SmoothingLevels.Moderate:
        pos = vecMNOP;
        break;
    case SmoothingLevels.Severe:
        pos = vecIJKLMNOP;
        break;
    case SmoothingLevels.Extreme:
        pos = vecABCDEFGHIJKLMNOP;
        break;
}

//apply pos to your target object