C# 和 XNA——如何使用 lerp 使 3d 模型跟随另一个 3d 模型
C# and XNA -- How to make 3d model follow another 3d model using lerp
我正在编写我正在制作的 3d 游戏的敌人 class,并且正在努力让敌人跟随玩家。我希望敌人基本上每一帧都朝着玩家的方向旋转一点,每一帧向前移动一点。我尝试使用 Lerping 来完成此操作,如下面的代码所示,但我似乎无法让它工作。玩的时候,敌人根本不出现在我的视野里,根本不追我。下面是我的敌人 class 的代码。
注意:p是我追逐的玩家对象的引用,world是敌方对象的世界矩阵,quaternion是这个敌方对象的四元数。
我目前的策略是在我的敌人的前向向量和玩家的位置向量之间找到方向向量,然后按照由速度变量确定的量对它进行 lerping。然后,我尝试找到由敌人的前向矢量和我称为 midVector.Then 的新锯齿矢量确定的平面的垂直矢量,我更新我的四元数以使玩家围绕该垂直矢量旋转。这是下面的代码:
//here I get the direction vector in between where my enemy is pointing and where the player is located at
Vector3 midVector = Vector3.Lerp(Vector3.Normalize(world.Forward), Vector3.Normalize(Vector3.Subtract(p.position,this.position)), velocity);
//here I get the vector perpendicular to this middle vector and my forward vector
Vector3 perp=Vector3.Normalize(Vector3.Cross(midVector, Vector3.Normalize(world.Forward)));
//here I am looking at the enemy's quaternion and I am trying to rotate it about the axis (my perp vector) with an angle that I determine which is in between where the enemy object is facing and the midVector
quaternion = Quaternion.CreateFromAxisAngle(perp, (float)Math.Acos(Vector3.Dot(world.Forward,midVector)));
//here I am simply scaling the enemy's world matrix, implementing the enemy's quaternion, and translating it to the enemy's position
world = Matrix.CreateScale(scale) * Matrix.CreateFromQuaternion(quaternion) * Matrix.CreateTranslation(position);
//here i move the enemy forward in the direciton that it is facing
MoveForward(ref position, quaternion, velocity);
}
private void MoveForward(ref Vector3 position, Quaternion rotationQuat, float speed)
{
Vector3 addVector = Vector3.Transform(new Vector3(0, 0, -1), rotationQuat);
position += addVector * speed;
}
我的问题是,我现在的 strategy/implementation 有什么问题,有没有更简单的方法让我完成这个(第一部分更重要)?
您没有逐帧存储对象的方向。我想你在想你正在创建的四元数是面向对象新方向的。但实际上,它只是一个四元数,只表示上一帧和当前帧之间的旋转差异,而不是整体方向。
所以需要做的是你的新 quat 必须应用于最后一帧的方向四元数以获得当前帧方向。
换句话说,您创建的是帧间更新四元数,而不是最终方向四元数。
你需要做这样的事情:
enemyCurrentOrientation = Quaternion.Concatenate(lastFrameQuat, thisNewQuat);
可能有更简单的方法,但如果这种方法适合您,则无需更改。
我正在编写我正在制作的 3d 游戏的敌人 class,并且正在努力让敌人跟随玩家。我希望敌人基本上每一帧都朝着玩家的方向旋转一点,每一帧向前移动一点。我尝试使用 Lerping 来完成此操作,如下面的代码所示,但我似乎无法让它工作。玩的时候,敌人根本不出现在我的视野里,根本不追我。下面是我的敌人 class 的代码。
注意:p是我追逐的玩家对象的引用,world是敌方对象的世界矩阵,quaternion是这个敌方对象的四元数。
我目前的策略是在我的敌人的前向向量和玩家的位置向量之间找到方向向量,然后按照由速度变量确定的量对它进行 lerping。然后,我尝试找到由敌人的前向矢量和我称为 midVector.Then 的新锯齿矢量确定的平面的垂直矢量,我更新我的四元数以使玩家围绕该垂直矢量旋转。这是下面的代码:
//here I get the direction vector in between where my enemy is pointing and where the player is located at
Vector3 midVector = Vector3.Lerp(Vector3.Normalize(world.Forward), Vector3.Normalize(Vector3.Subtract(p.position,this.position)), velocity);
//here I get the vector perpendicular to this middle vector and my forward vector
Vector3 perp=Vector3.Normalize(Vector3.Cross(midVector, Vector3.Normalize(world.Forward)));
//here I am looking at the enemy's quaternion and I am trying to rotate it about the axis (my perp vector) with an angle that I determine which is in between where the enemy object is facing and the midVector
quaternion = Quaternion.CreateFromAxisAngle(perp, (float)Math.Acos(Vector3.Dot(world.Forward,midVector)));
//here I am simply scaling the enemy's world matrix, implementing the enemy's quaternion, and translating it to the enemy's position
world = Matrix.CreateScale(scale) * Matrix.CreateFromQuaternion(quaternion) * Matrix.CreateTranslation(position);
//here i move the enemy forward in the direciton that it is facing
MoveForward(ref position, quaternion, velocity);
}
private void MoveForward(ref Vector3 position, Quaternion rotationQuat, float speed)
{
Vector3 addVector = Vector3.Transform(new Vector3(0, 0, -1), rotationQuat);
position += addVector * speed;
}
我的问题是,我现在的 strategy/implementation 有什么问题,有没有更简单的方法让我完成这个(第一部分更重要)?
您没有逐帧存储对象的方向。我想你在想你正在创建的四元数是面向对象新方向的。但实际上,它只是一个四元数,只表示上一帧和当前帧之间的旋转差异,而不是整体方向。
所以需要做的是你的新 quat 必须应用于最后一帧的方向四元数以获得当前帧方向。
换句话说,您创建的是帧间更新四元数,而不是最终方向四元数。
你需要做这样的事情:
enemyCurrentOrientation = Quaternion.Concatenate(lastFrameQuat, thisNewQuat);
可能有更简单的方法,但如果这种方法适合您,则无需更改。