向量
向量 是一个有大小和方向的数学对象。在三维空间中,向量通常表示为 (v_x, v_y, v_z)
。
基本操作
-
加法:
a + b = (a_x + b_x, a_y + b_y, a_z + b_z)
-
减法:
a - b = (a_x - b_x, a_y - b_y, a_z - b_z)
-
标量乘法:
k * v = (k * v_x, k * v_y, k * v_z)
-
模(长度):
||v|| = sqrt(v_x^2 + v_y^2 + v_z^2)
-
归一化:
Normalized(v) = v / ||v||
点乘(Dot Product)
点乘 计算两个向量的内积,结果是一个标量。公式为:
a · b = a_x * b_x + a_y * b_y + a_z * b_z
应用
-
光照计算:
Intensity = max(0, N · L)
其中
N
是法线向量,L
是光源方向向量。 -
夹角计算:
cos(θ) = (a · b) / (||a|| * ||b||)
-
投影:
Projection of a onto b = (a · b) / ||b||
叉乘(Cross Product)
叉乘 计算两个向量的外积,结果是一个垂直于原来的两个向量的向量。公式为:
a × b = (a_y * b_z - a_z * b_y, a_z * b_x - a_x * b_z, a_x * b_y - a_y * b_x)
应用
-
法线计算:
N = A × B
-
旋转: 叉乘用于计算物体旋转时的旋转轴和角度。
-
计算平行四边形面积:
Area = ||a × b||
在 Unity 中的应用
-
光照计算: 使用点乘计算光照强度,特别是在实现漫反射和镜面反射时。
-
法线计算: 使用叉乘计算物体表面的法线向量,用于光照和碰撞检测。
-
物体移动和旋转: 使用向量操作计算物体的移动、旋转和缩放。
-
碰撞检测: 使用向量来计算物体间的距离和相对位置,判断是否发生碰撞。
图形学中的应用
-
光照模型: 点乘用于计算漫反射光照强度,叉乘用于计算法线向量。
-
计算视角: 通过点乘计算视角的大小,用于相机视角和景深效果。
-
变换矩阵: 向量运算用于计算变换矩阵,进行模型、视图和投影的变换。
-
物体表面属性: 使用法线向量和光源方向向量进行阴影计算和表面细节渲染。
-
基于Unity:源码解析,unity进行了封装,大概是这意思
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace Ethan { public struct Vector3 { public float x, y, z; public Vector3(float x, float y, float z) { this.x = x; this.y = y; this.z = z; } /// <summary> /// 两个向量之和 /// 应用:向前位移、力的合成、可取 /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static Vector3 operator +(Vector3 a, Vector3 b) { return new Vector3(a.x + b.y, a.y + b.y, a.z + b.z); } /// <summary> /// 两个向量之差 /// 应用:向后位移、计算反作用力 /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static Vector3 operator -(Vector3 a, Vector3 b) { return new Vector3(a.x - b.y, a.y - b.y, a.z - b.z); } /// <summary> /// 计算向量和标量的乘法 /// 应用:放大或缩小物体的模型、位移计算、计算力、加速度等物理量时,经常需要将向量与标量相乘 /// </summary> /// <param name="k"></param> /// <param name="v"></param> /// <returns></returns> public static Vector3 operator *(Vector3 v, float k) { return new Vector3(k * v.x, k * v.y, k * v.z); } /// <summary> /// 计算两点之间的距离 /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static float Disance(Vector3 a, Vector3 b) { return Mathf.Sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z)); } /// <summary> /// 计算向量-标准化(求模) /// 应用:主要用来计算向量的长度或大小 /// </summary> public float Magnitude { get { return Mathf.Sqrt(x * x + y * y + z * z); } } /// <summary> /// 向量 归一化 /// 将向量转换为单位向量(长度为 1 的向量),保留方向但调整大小 /// 应用:单位向量在方向计算、光照计算、法线计算 /// </summary> public Vector3 Normalized { get { float mag = this.Magnitude; if (mag > 0) { return this * (1 / mag); } return new Vector3(0, 0, 0); // 返回一个零向量,如果原向量的长度为零 } } /// <summary> /// 点乘 /// 应用:光照计算、背面裁剪、计算投影 /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static float Dot(Vector3 a, Vector3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; } /// <summary> /// 叉乘 /// 应用: /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static Vector3 Cross(Vector3 a, Vector3 b) { return new Vector3( a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x ); } } }