定义:
1.点乘:向量a在向量b上的投影长度*b的模长
a⋅b=|a||b|θ*cosθ
a⋅b=|a|cosθ*|b|
|a|cosθ是a投影在b上的长度,再乘|b|就是点乘结果了
结果:dot>0 同向;dot<0 反向;dot==0 垂直
疑问:如果只是确定方位,为什么要用点乘,直接|a|*cosθ不可以吗
原因:点乘还有另一条公式 a·b=x1x2+y1y2+z1z2 这条公式天然的将长度和角度计算在一起而不用考虑两者之间的夹角,而|a|*cosθ需要计算夹角和模长
总结:点乘其实并不需要理解数值大小代表了什么,只需要考虑dot>0,dot<0表示什么就可以了
实例
1.向量的点乘和叉乘可以获取方位
以前的项目有遇到过这种情况:需要知道玩家相对于另一个物体的方位。
对向量a和向量b分别做叉乘和点乘,得到如下结果:
a.通过叉乘的左手法则我们可以知道:
叉乘y值>0的时候,a在b的左边;
叉乘y值<0的时候,a在b的右边
b.通过点乘我们可以知道:
当点乘>0的时候,两个向量所成的夹角<90,为锐角,a在b的前面;
当点乘<0的时候,两个向量所成的夹角>90,为钝角,a在b的后面
两者结合,就可以获取两个向量的前后左右方位了,具体应用如下
public class VectorTest : MonoBehaviour
{
public Transform player; //玩家
public Transform cube; //其他物体
public Text txt;
private void Update()
{
Vector3 playerForward = player.forward; //玩家看向方向
Vector3 playerToCube = cube.position - player.position; //player->cube 向量
Debug.DrawLine(Vector3.zero, playerForward, Color.green);
Debug.DrawLine(Vector3.zero, playerToCube, Color.red);
Vector3 cross = Vector3.Cross(playerToCube, playerForward); //确定左右
float dot = Vector3.Dot(playerToCube, playerForward); //确定前后
//cube在玩家的左边
if(cross.y > 0)
{
//cube在玩家的前面
if(dot > 0)
{
txt.text = "cube在玩家的左前方";
}
else if(dot < 0)
{
txt.text = "cube在玩家的左后方";
}
else
{
txt.text = "cube在玩家的正左方";
}
}
//右边
else if(cross.y < 0)
{
//cube在玩家的前面
if (dot > 0)
{
txt.text = "cube在玩家的右前方";
}
else if (dot < 0)
{
txt.text = "cube在玩家的右后方";
}
else
{
txt.text = "cube在玩家的正右方";
}
}
else //cross.y==0的情况,说明两个向量的z轴都为0,应该看cross.z,如果cross.z也为0的情况,则看cross.x
{
txt.text = "无法判断";
}
}
}
上面的代码可以获取玩家和物体的方位,首先根据叉乘获取左右方向,之后再根据点乘获取前后方向。
其实判断方位有另一种办法,只需要靠点乘就可以,但是前提是需要知道一个物体b的forawrd向量和right向量。先用物体a.position-b.position,得出一个向量p,由p与b.forward做点乘dot
dot>0,a在b的前方;
dot<0,a在b的后方
再与b.right做点乘dot
dot>0,a在b的右方;
dot<0,a在b的左方
通过与两个方向做点乘,就可以知道前后左右的方位了
Unity中四元数与欧拉角相乘
Quaternion * Vector3 表示一个Vector3方向向量经过Quaternion四元数转换后得到的新的方向向量
于是可以得到下面的一个函数
//旋转一个方向向量
//direction 方向向量
//euler 欧拉角
public static Vector3 Rotate(Vector3 direction, Vector3 euler)
{
//将一个方向向量旋转euler度
Vector3 newVector = Quaternion.Euler(euler) * direction;
return newVector;
}
//将一个欧拉角转换为方向向量
public static Vector3 EulerToDirection(Vector3 euler)
{
//必须用Vector3.forward,这样旋转得到的方向向量才是正确的
Vector3 newVector = Quaternion.Euler(euler) * Vector3.forward;
return newVector;
}
点乘与法向量,平面的关系
我们知道一个法向量n,那么法向量和这个平面的点乘即为0(90度)
有一点p在平面上方,平面中的一点t,则有下面的结论:
如果(p-t)·n>0,则表示p在平面上方(正面) ;
如果(p-t)·n<0,则表示p在平面下方(反面),如图2
[图2]