數學:笛卡爾座標系
計算機(屏幕座標系):以屏幕左上角(標準座標系)或者屏幕左下角(Cocos2d)爲原點算法
左手系 unity
右手系c#
Y UP 3dmax
Z UP maya數組
具備大小和方向,通常經常使用於表示勢能、位移和速度。有時咱們也用向量來表示一個單個方向,好比玩家在3D遊戲中觀察的方向、多邊形面對的方向、光線的傳播方向以及從一個物體表面折回的反射光方向。app
A(x1,y1,z1) B(x2,y2,z2) AB=(x2-x1,y2-y1,z2-z1)
向量的數乘
n*(x,y,z) = (nx,ny,nz)dom
Unity下在cube下掛載下列程序,模擬x,y,z向移動ide
using System.Collections; using System.Collections.Generic; using UnityEngine; public class axis : MonoBehaviour { public float speed = 0f; public Vector3 dir = new Vector3(0, 0, 0); // Use this for initialization void Start () { } // Update is called once per frame void Update () { Vector3 pre = this.gameObject.transform.position; Vector3 now = dir * speed + pre; this.gameObject.transform.position = now; } }
自定義加減法和normalize,與Unity原身進行比較
新建Vector3d.cs,添加到componentthis
using System.Collections; using System; using System.Collections.Generic; public class Vector3d { public float x, y, z; public Vector3d(float x=0f,float y=0f,float z = 0f) { this.x = x; this.y = y; this.z = z; } public Vector3d(Vector3d vec) { this.x = vec.x; this.y = vec.y; this.z = vec.z; } public Vector3d add(Vector3d vec) { Vector3d ret = new Vector3d(x, y, z); ret.x += vec.x; ret.y += vec.y; ret.z += vec.z; return ret; } public Vector3d sub(Vector3d vec) { Vector3d ret = new Vector3d(x, y, z); ret.x -= vec.x; ret.y -= vec.y; ret.z -= vec.z; return ret; } public void normalize() { float length = (float)Math.Sqrt(x * x + y * y + z * z); x /= length; y /= length; z /= length; } public override string ToString() { return string.Format("("+x+","+y+","+z+")"); } public static Vector3d operator +(Vector3d lv,Vector3d rv) { return lv.add(rv); } public static Vector3d operator -(Vector3d lv,Vector3d rv) { return lv.sub(rv); } }
比較程序以下:3d
using System.Collections; using System.Collections.Generic; using UnityEngine; public class axis : MonoBehaviour { public bool isEqual(Vector3d ov,Vector3 uv) { if (ov.x == uv.x && ov.y == uv.y && ov.z == uv.z) { return true; } return false; } void Start () { Vector3d ov1 = new Vector3d(1.1f, 1.2f, 1.3f) + new Vector3d(1, 2, 3); Vector3 uv1 = new Vector3(1.1f, 1.2f,1.3f) + new Vector3(1, 2, 3); if (isEqual(ov1, uv1)) { Debug.Log("add equal ..."); } Vector3d ov2 = new Vector3d(1.1f, 1.2f, 1.3f) - new Vector3d(1, 2, 3); Vector3 uv2 = new Vector3(1.1f, 1.2f, 1.3f) - new Vector3(1, 2, 3); if (isEqual(ov2, uv2)) { Debug.Log("sub equal ..."); } ov2.normalize(); uv2.Normalize(); if (isEqual(ov2, uv2)) { Debug.Log("nrm equal ..."); } } }
u = (x1,y1,z1),v = (x2,y2,z2) u x v = (y1*z2-z1*y2,z1*x2-x1*z2,x1*y2-y1*x2)
代碼以下:code
public Vector3d cross(Vector3d vec) { Vector3d ret = new Vector3d(); ret.x = y * vec.z - z * vec.y; ret.y = z * vec.x - x * vec.z; ret.z = x * vec.y - y * vec.x; return ret; }
比較結果:component
Vector3d ov3 = new Vector3d(1, 2, 3).cross(new Vector3d(-5, 7, 10)); Vector3 uv3 = Vector3.Cross(new Vector3(1, 2, 3), new Vector3(-5, 7, 10)); if (isEqual(ov3, uv3)) { Debug.Log("cross equal ..."); }
u = (x1,y1,z1),v = (x2,y2,z2) u · v = x1*x2+y1*y2+z1*z2 餘弦定理: u · v = |u||v|cos(a)
a爲u與v的夾角
u · v = 0,u與v相互垂直
u · v > 0,u與v夾角小於90
u · v < 0,u與v夾角大於90
假如:u和v都是一個單位向量,
u · v = cos(a) => -1<=cos(a)<=1
用一個向量表示光照顏色。最後的平面的光照顏色=光照顏色*cos(a)
在Unity中新建一個小球,而後添加meterial,新建一個Shader,代碼以下,模擬光照效果:
Shader "Custom/Color" { Properties { _Color ("Light Color", Color) = (1,1,1,1) // 白色 _Dir ("Light Dir", Vector) = (0,0,1,0) _Intensity("Intensity",float) = 1.0 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct v2f { float4 vertex: POSITION; float3 normal: NORMAL; }; fixed4 _Color; fixed4 _Dir; float _Intensity; v2f vert(appdata_base v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.normal = v.normal; return o; } // 光照算法 fixed4 frag(v2f i) : COLOR{ fixed3 dir = fixed3(-_Dir.x, -_Dir.y, -_Dir.z); dir = normalize(dir); fixed3 nrm = normalize(i.normal); float bis = dot(dir, nrm); if (bis <= 0) { bis = 0; } fixed4 col = _Color * bis * _Intensity; //光照顏色 return col; } ENDCG } } }
光照算法核心代碼:
// 光照算法 fixed4 frag(v2f i) : COLOR{ fixed3 dir = fixed3(-_Dir.x, -_Dir.y, -_Dir.z); dir = normalize(dir); fixed3 nrm = normalize(i.normal); float bis = dot(dir, nrm); if (bis <= 0) { bis = 0; } fixed4 col = _Color * bis * _Intensity; //光照顏色 return col; }
效果以下:
定義:一個m x n的矩陣M是一個m行n列的矩形實數數組。行和列指定了矩陣的維數。矩陣中數值稱爲元素。
矩陣的加、減法
矩陣的數乘
A(B+C)=AB+AC
(AB)C=A(BC)
代碼檢驗:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class axis : MonoBehaviour { // Use this for initialization void Start () { Matrix4x4 a = new Matrix4x4(); for(int i = 0; i < 16; i++) { a[i] = Random.Range(1, 100.0f); } Matrix4x4 b = new Matrix4x4(); for (int i = 0; i < 16; i++) { b[i] = Random.Range(1, 100.0f); } Debug.Log(a * b); // a * b = (b的轉置矩陣 * a的轉置矩陣)的轉置矩陣 Matrix4x4 c = a.transpose;//轉置矩陣 Matrix4x4 d = b.transpose; Debug.Log((d * c).transpose); } // Update is called once per frame void Update () { } }
Debug.Log(this.transform.localToWorldMatrix);
(x,y,z,0)用於描述向量
(x,y,z,1)用於描述點
原始單位大小,位於原點:
1.00000 0.00000 0.00000 0.00000
0.00000 1.00000 0.00000 0.00000
0.00000 0.00000 1.00000 0.00000
0.00000 0.00000 0.00000 1.00000
在x軸-1單位,y軸2單位,z軸6單位:
1.00000 0.00000 0.00000 -1.00000
0.00000 1.00000 0.00000 2.00000
0.00000 0.00000 1.00000 6.00000
0.00000 0.00000 0.00000 1.00000
Debug.Log(this.transform.localToWorldMatrix.transpose); // 轉置後對應座標原點
1.00000 0.00000 0.00000 0.00000
0.00000 1.00000 0.00000 0.00000
0.00000 0.00000 1.00000 0.00000
-1.00000 2.00000 6.00000 1.00000
假設咱們經過一個最小點(-4,-4,0)和一個最大點(4,4,0)定義一個正方形,咱們但願將正方形沿着x軸縮小0.5倍,y軸放大2.0倍,z抽不變。那麼對應的縮放矩陣爲:
0.5 0 0 0
0 2 0 0
0 0 1 0
0 0 0 1
顯示結果:
0.50000 0.00000 0.00000 0.00000
0.00000 2.00000 0.00000 0.00000
0.00000 0.00000 1.00000 0.00000
-1.00000 2.00000 6.00000 1.00000
x(1,0,0)旋轉角度a,對應矩陣
1 0 0 0
0 cos(a) sin(a) 0
0 -sin(a) cos(a) 0
0 0 0 1
在x軸旋轉30度:
1.00000 0.00000 0.00000 0.00000
0.00000 0.86603 0.50000 0.00000
0.00000 -0.50000 0.86603 0.00000
0.00000 0.00000 0.00000 1.00000
如今給定射線 p(t)= p0 + t*u
平面:n·(p-p1)=0
那麼射線與平面的關係爲:
t=(n·p1 - n·p0)/n·u
若t>=0,則射線與平面相交,且交點爲p0+t*u 若t<0,則不相交