上次寫了動態繪製立方體,這最近又來了新功能,繪製圓柱(風筒),要求是給了不少節點,根據節點去動態繪製風筒,風筒就是圓柱鏈接而成的,能夠理解爲管道,還有就是拐角處注意倒角,圓潤過分過來。html
動態繪製圓柱mesh,注意,圓柱的mesh繪製遠比立方體複雜得多,上節闡述過基本mesh建立立方體,有興趣能夠去看看http://www.javashuo.com/article/p-ynhoctvw-hp.html,頂點以及倒角須要你本身去插值出來,其中倒角是使用貝塞爾曲線插值過分出來的。算法
1.頂點座標ide
2.uv座標函數
3.構建索引測試
4.構建實體this
構建圓柱應當理解爲這是多個圓插值出來的,首先設置圓的頂點座標,首先說第一種方式,我先前考慮,在世界座標空間中,建立一個Gamobject經過它的座標做爲圓上頂點座標,不從本地建立座標了(由於涉及座標轉換,矩陣變換),因此我用了這種方式spa
第一種方式:線程
具體代碼:3d
/// <summary> /// 設置起中間點斷面頂點數據 /// </summary> /// <param name="currPos">當前點座標</param> /// <param name="curDirection">朝向</param> /// <param name="radius">半徑</param> private void SetSectionVertexData(Vector3 currPos, Vector3 curDirection, float radius,float u) { // 首先計算導線點相對場景中心點的偏移座標 Vector3 position = currPos - center; // 計算direction、right、up向量(注:Unity3d中使用左手座標系) Vector3 direction = curDirection.normalized; Vector3 right = Vector3.Cross(Vector3.up, direction).normalized; Vector3 up = Vector3.Cross(direction, right).normalized; angleStep = 360.0f / (float)devide; GameObject gameObject = new GameObject(); gameObject.transform.position = position + radius * right;for (int i = 0; i < 360.0f; i += (int)angleStep) { gameObject.transform.RotateAround(currPos, direction, angleStep); vertices.Add(gameObject.transform.position); } Destroy(gameObject); }
代碼中direction是方向向量(上一點指向下一點座標),構建頂點也須要順序,我這是在右側90度逆時針建立的,gameObject.transform.position = position + radius * right;這是起點頂點,一共十個頂點。code
第二種方式:
我已經用第一種方式功能都作完了,建立好了,完事領導說咱們風筒可能要在子線程建立,哇,一瞬間透心涼,GameObject就意味着淘汰了,矩陣變換是躲不開了。從本地建立圓,這句話的意思是指模型本地座標,即左手座標系(0,0,0)點 找一點爲(0,0,0)點去建立。
具體代碼:
1 /// <summary> 2 /// 設置起點圓頂點數據 3 /// </summary> 4 /// <param name="startPos">起點座標</param> 5 /// <param name="nextPos">下一點座標</param> 6 private void SetStartVertexData(Vector3 startPos, Vector3 nextPos) 7 { 8 // 首先計算導線點相對場景中心點的偏移座標 9 Vector3 position = startPos - center; 10 Vector3 nextPosition = nextPos - center; 11 12 // 計算direction、right、up向量(注:Unity3d中使用左手座標系) 13 Vector3 direction = (nextPosition - position).normalized;//z軸 14 Vector3 right = Vector3.Cross(Vector3.up, direction).normalized;//x軸,右 15 Vector3 up = Vector3.Cross(direction, right).normalized;//x和z獲得up 16 // 設起點圓定點數據 17 SetSectionVertexData(position, direction, up, right, uvPosU); 18 } 19 20 21 /// <summary> 22 /// 設置斷面頂點數據 23 /// </summary> 24 /// <param name="currentPos">當前點座標</param> 25 /// <param name="direction">朝向</param> 26 private void SetSectionVertexData(Vector3 currentPos, Vector3 direction, Vector3 up, Vector3 right, float u) 27 { 28 // 構建旋轉矩陣 29 Matrix4x4 m = Utils.MakeBasis(right, up, direction); 30 for (float i = 0f; i < 360.0f; i += 36.0f) 31 { 32 // 計算頂點 33 float rad = Mathf.Deg2Rad * i; 34 Vector3 targetPos = currentPos + m.MultiplyPoint3x4(new Vector3(Mathf.Cos(rad) * radius, Mathf.Sin(rad) * radius, 0.0f)); 35 // 計算V座標 36 float v = ((baseValue * 36.0f) / 360.0f); 37 // 保存頂點座標&紋理座標 38 vertices.Add(targetPos); 39 } 40 }
這裏解釋下,過程是這樣的,在本地座標構建圓,經過旋轉矩陣變換到世界座標。Vector3 direction = (nextPosition - position).normalized;,通常將指向方向向量爲座標系Z軸,假設y軸(0,1,0)爲Up方向,那麼Vector3 right = Vector3.Cross(Vector3.up, direction).normalized;Z軸與假設Y軸的叉乘獲得的是X軸的方向向量(即right方向),垂直與zy平面,可是接下來求方向向量(Z軸)與X軸的叉乘,指定是咱們要的Y方向,由於肯定的Z和X(垂直XZ平面)。
Utils.MakeBasis具體邏輯以下:
1 /// <summary> 2 /// 經過座標軸構建矩陣 3 /// </summary> 4 /// <param name="xAxis">x軸</param> 5 /// <param name="yAxis">y軸</param> 6 /// <param name="zAxis">z軸</param> 7 /// <returns>4x4矩陣</returns> 8 public static Matrix4x4 MakeBasis(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis) 9 { 10 Matrix4x4 mat = Matrix4x4.identity; 11 12 mat.m00 = xAxis.x; 13 mat.m10 = xAxis.y; 14 mat.m20 = xAxis.z; 15 16 mat.m01 = yAxis.x; 17 mat.m11 = yAxis.y; 18 mat.m21 = yAxis.z; 19 20 mat.m02 = zAxis.x; 21 mat.m12 = zAxis.y; 22 mat.m22 = zAxis.z; 23 24 return mat; 25 }
矩陣就不解釋了,本身看吧。Matrix4x4 m = Utils.MakeBasis(right, up, direction);這是在獲得所構建節點的座標系即座標走向。由於要把構建的圓放到該點座標下。m.MultiplyPoint3x4是將構建圓的頂點轉換到當前點座標系下,new Vector3(Mathf.Cos(rad) * radius, Mathf.Sin(rad) * radius, 0.0f)圓上點座標XY平面構建元,Z爲0,到這裏圓心始終是(0,0,0),那麼將這個圓放到目標點下須要再加上目標點在當下座標系的偏移量(即座標值)。因此加currentPos。
到這就將兩種設置頂點座標方式說完了。還有就是拐角處圓的構建,須要用貝塞爾曲線差值出來。
代碼:
1 /// <summary> 2 /// 設置中間點頂點數據 3 /// </summary> 4 /// <param name="currentPos"></param> 5 /// <param name="prevPos"></param> 6 /// <param name="nextPos"></param> 7 private void SetPrepareVertexData(Vector3 currentPos, Vector3 prevPos, Vector3 nextPos) 8 { 9 // 首先計算導線點相對場景中心點的偏移座標 10 Vector3 prevPosition = prevPos - center; 11 Vector3 position = currentPos - center; 12 Vector3 anitherposition = nextPos - center; 13 14 // 計算前一段巷道的direction、right、up向量(注:Unity3d中使用左手座標系) 15 Vector3 prevDirection = (position - prevPosition).normalized; 16 Vector3 prevRight = Vector3.Cross(Vector3.up, prevDirection).normalized; 17 Vector3 prevUp = Vector3.Cross(prevDirection, prevRight).normalized; 18 19 // 計算後一段巷道的direction、right、up向量(注:Unity3d中使用左手座標系) 20 Vector3 anitherDirection = (anitherposition - position).normalized; 21 Vector3 anitherlRight = Vector3.Cross(Vector3.up, anitherDirection).normalized; 22 Vector3 anitherUp = Vector3.Cross(anitherDirection, anitherlRight).normalized; 23 24 float angle = Vector3.Angle(-prevDirection, anitherDirection); 25 26 if (angle >= 179.0) 27 { 28 //生成斷面數據不倒角處理 29 uvPosU += (GetPointDistance(position, prevPosition) / textureSizeL); 30 SetSectionVertexData(position, prevDirection, prevUp, prevRight, uvPosU); 31 return; 32 } 33 //倒角處理 34 35 //先後兩段風筒長度 36 float PrevLength = Vector3.Distance(position, prevPosition); 37 float anithorLength = Vector3.Distance(position, anitherposition); 38 39 indentationValue = PrevLength > anithorLength ? (anithorLength * 0.25f) : (PrevLength * 0.25f);//縮進爲短風筒的1/4 40 41 // 計算縮進後的位置 42 Vector3 prevEnd = position - prevDirection * indentationValue;//左 43 Vector3 behindStart = position + anitherDirection * indentationValue;// 右 44 45 uvPosU += (GetPointDistance(prevPosition, prevEnd) / textureSizeL); 46 // 生成前段結束斷面頂點數據 47 SetSectionVertexData(prevEnd, prevDirection, prevUp, prevRight, uvPosU); 48 49 // 生成中間倒角斷面頂點數據 50 //插值0-1 51 float timer = 0.1f; 52 Vector3 prevpos = prevEnd; 53 for (float i = 1.0f; i <= 9.0f; i++) 54 { 55 Vector3 pos = Utils.CalculateCubicBezierPoint(timer, prevEnd, position, behindStart); 56 // 計算斷面方向 57 Vector3 direction = (pos - prevpos).normalized; 58 Vector3 right = Vector3.Cross(Vector3.up, direction).normalized; 59 Vector3 up = Vector3.Cross(direction, right).normalized; 60 uvPosU += (GetPointDistance(pos, prevpos) / textureSizeL); 61 // 生成斷面頂點數據 62 SetSectionVertexData(pos, direction, up, right, uvPosU); 63 //遞增插值時間 64 timer += 0.1f; 65 //更新前一個點座標 66 prevpos = pos; 67 } 68 // 生成後段起始斷面頂點數據 69 SetSectionVertexData(behindStart, anitherDirection, anitherUp, anitherlRight, ++uvPosU); 70 }
1到9插10個圓。須要找拐角處先後兩個點分別爲開始和結束插值點,Utils.CalculateCubicBezierPoint(timer, prevEnd, position, behindStart);timer爲每次插值(可理解爲時刻)。此函數(三階貝塞爾曲線)具體邏輯:
1 /// <summary> 2 /// 計算三階貝塞爾曲線點座標 3 /// </summary> 4 /// <param name="t">時刻(0.0~1.0)</param> 5 /// <param name="p0">起點座標</param> 6 /// <param name="p1">中間點座標</param> 7 /// <param name="p2">終點座標</param> 8 /// <returns>座標點</returns> 9 public static Vector3 CalculateCubicBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2) 10 { 11 float u = 1.0f - t; 12 float tt = t * t; 13 float uu = u * u; 14 15 return (p0 * uu + p1 * 2 * u * t + p2 * tt); 16 }
這樣準備頂點座標就結束了。
UV座標是與頂點一一對應的,因此在建立頂點時最好一塊兒計算出來,我這裏的要求是,上下面貼想同紋理,並且是重複帖,因此V向基本就貼1次上下兩面貼,就要從圓上10個點分紅兩半,或者按角度角度分,通常從0-1後一半從1-0這樣就能夠實現,重點是U方向座標值的計算,每一個橫向重複帖不少次紋理,須要根據貼圖比例以及長度去設置,可是U的值應該是累加的。一次從起點到終點貼。知道這一點就好辦了。
代碼:
//橫向代碼,U是累加的,根據圓柱長度去設置計算。 uvPosU += (GetPointDistance(pos, prevpos) / textureSizeL); //V方向按上述規律貼 /// <summary> /// 設置斷面頂點數據 /// </summary> /// <param name="currentPos">當前點座標</param> /// <param name="direction">朝向</param> private void SetSectionVertexData(Vector3 currentPos, Vector3 direction, Vector3 up, Vector3 right, float u) { // 構建旋轉矩陣 Matrix4x4 m = Utils.MakeBasis(right, up, direction); int baseValue = 2; for (float i = 0f; i < 360.0f; i += 36.0f) { // 計算頂點 float rad = Mathf.Deg2Rad * i; Vector3 targetPos = currentPos + m.MultiplyPoint3x4(new Vector3(Mathf.Cos(rad) * radius, Mathf.Sin(rad) * radius, 0.0f)); // 計算V座標 float v = ((baseValue * 36.0f) / 360.0f); // 保存頂點座標&紋理座標 vertices.Add(targetPos); uvs.Add(new Vector2(u, v)); if (i > 108) { baseValue -= 2; } else { baseValue += 2; } } }
這float v = ((baseValue * 36.0f) / 360.0f);算法須要按要求設置。
構建索引就要按照定點順序去構建,鏈接圓與圓之間的曲面,索引值也是累加的好比這裏十個點,第一個圓是0-9/第二個10-19/以此類推。
1 /// <summary> 2 /// 設置索引數據 3 /// </summary> 4 private void SetIndexData() 5 { 6 int faceCount = (vertices.Count / devide) - 1; 7 int baseValue; 8 for (int i = 0; i < faceCount; i++) 9 { 10 baseValue = 0; 11 for (int j = 1; j <= 10; j++) 12 { 13 if (j < 10) 14 { 15 triangles.Add(i * 10 + baseValue); 16 triangles.Add(i * 10 + 11 + baseValue); 17 triangles.Add(i * 10 + baseValue + 10); 18 19 triangles.Add(i * 10 + baseValue); 20 triangles.Add(i * 10 + baseValue + 1); 21 triangles.Add(i * 10 + 11 + baseValue); 22 } 23 else 24 { 25 triangles.Add(i * 10 + baseValue); 26 triangles.Add(i * 10 + 10); 27 triangles.Add(i * 10 + baseValue + 10); 28 29 triangles.Add(i * 10 + baseValue); 30 triangles.Add(i * 10); 31 triangles.Add(i * 10 + 10); 32 } 33 baseValue++; 34 } 35 } 36 }
注意構建順序否則順逆時針容易反了。
這裏解釋最後一步了,也是最簡單的一步了,不解釋上代碼:
1 /// <summary> 2 /// 繪製風筒實體 3 /// </summary> 4 /// <param name="posList">風筒節點數據集合</param> 5 /// <param name="radius">風筒半徑</param> 6 public void DrawAirDuct(List<Vector3> posList, float radius) 7 { 8 this.radius = radius; 9 PrepareVertexData(posList); 10 SetIndexData(); 11 Mesh mesh = new Mesh 12 { 13 vertices = vertices.ToArray(), 14 triangles = triangles.ToArray(), 15 uv = uvs.ToArray(), 16 }; 17 mesh.RecalculateNormals(); 18 GameObject airDuctObj = new GameObject(name); 19 airDuctObj.AddComponent<MeshFilter>().mesh = mesh; 20 airDuctObj.AddComponent<MeshRenderer>().material = new Material(Resources.Load<Material>("Materials/Mine/LanewayColor")); 21 22 // 添加碰撞器MeshCollider 23 airDuctObj.AddComponent<MeshCollider>(); 24 }
切記別忘了從新計算法線mesh.RecalculateNormals();這纔出預期效果。
完整代碼:
1 using System; 2 using System.Collections.Generic; 3 using UnityEngine; 4 5 namespace Tx3d.Framework 6 { 7 /// <summary> 8 /// 繪製風筒實體 9 /// </summary> 10 public class AirDuct : Entity 11 { 12 #region Fields 13 14 //計算圓角的縮進值 15 private float indentationValue; 16 17 //圓劃分爲多少等份 18 private int devide = 10; 19 20 //中心點座標 21 private Vector3 center = Vector3.zero; 22 23 //頂點座標集合 24 private List<Vector3> vertices = new List<Vector3>(); 25 26 //uv座標集合 27 private List<Vector2> uvs = new List<Vector2>(); 28 29 //索引集合 30 private List<int> triangles = new List<int>(); 31 32 //半徑 33 private float radius; 34 35 //貼圖長度縮放尺寸 36 private float textureSizeL = 10.24f; 37 38 //uv座標的u座標值 39 private float uvPosU = 0; 40 41 #endregion 42 43 #region Public Methods 44 45 /// <summary> 46 /// 風筒實體 47 /// </summary> 48 /// <param name="name">實體名</param> 49 public AirDuct(string name) : base(name) 50 { 51 52 } 53 54 /// <summary> 55 /// 繪製風筒實體 56 /// </summary> 57 /// <param name="posList">風筒節點數據集合</param> 58 /// <param name="radius">風筒半徑</param> 59 public void DrawAirDuct(List<Vector3> posList, float radius) 60 { 61 this.radius = radius; 62 PrepareVertexData(posList); 63 SetIndexData(); 64 Mesh mesh = new Mesh 65 { 66 vertices = vertices.ToArray(), 67 triangles = triangles.ToArray(), 68 uv = uvs.ToArray(), 69 }; 70 mesh.RecalculateNormals(); 71 GameObject airDuctObj = new GameObject(name); 72 airDuctObj.AddComponent<MeshFilter>().mesh = mesh; 73 airDuctObj.AddComponent<MeshRenderer>().material = new Material(Resources.Load<Material>("Materials/Mine/LanewayColor")); 74 75 // 添加碰撞器MeshCollider 76 airDuctObj.AddComponent<MeshCollider>(); 77 } 78 79 /// <summary> 80 /// 釋放風筒實體 81 /// </summary> 82 public override void Dispose() 83 { 84 85 } 86 87 /// <summary> 88 /// 射線查詢 89 /// </summary> 90 /// <param name="ray">射線</param> 91 /// <param name="hit">拾取結果</param> 92 /// <param name="maxDistance">最大拾取距離</param> 93 /// <returns>拾取成功返回true,不然返回false</returns> 94 public override bool Raycast(Ray ray, out RaycastHit hit, float maxDistance) 95 { 96 var collider = gameObject.GetComponent<MeshCollider>(); 97 return collider.Raycast(ray, out hit, maxDistance); 98 } 99 100 /// <summary> 101 /// 體積查詢 <see cref="Entity.VolumeQuery(PlaneBoundedVolume)"/> 102 /// </summary> 103 /// <param name="volume">查詢體</param> 104 /// <returns>查詢成功返回true,不然返回false</returns> 105 public override bool VolumeQuery(PlaneBoundedVolume volume) 106 { 107 throw new NotImplementedException(); 108 } 109 110 #endregion 111 112 #region Private Methods 113 114 /// <summary> 115 /// 準備頂點數據 116 /// </summary> 117 private void PrepareVertexData(List<Vector3> posList) 118 { 119 for (int i = 0; i < posList.Count; i++) 120 { 121 //起點圓面 122 if (i == 0) 123 { 124 SetStartVertexData(posList[i], posList[i + 1]); 125 } 126 else if (i != posList.Count - 1) 127 { 128 ////中間點(求縮進點設置圓角) 129 SetPrepareVertexData(posList[i], posList[i - 1], posList[i + 1]); 130 } 131 else 132 { 133 //終點圓面 134 SetEndVertexData(posList[i], posList[i - 1]); 135 } 136 } 137 } 138 139 /// <summary> 140 /// 設置起點圓頂點數據 141 /// </summary> 142 /// <param name="startPos">起點座標</param> 143 /// <param name="nextPos">下一點座標</param> 144 private void SetStartVertexData(Vector3 startPos, Vector3 nextPos) 145 { 146 // 首先計算導線點相對場景中心點的偏移座標 147 Vector3 position = startPos - center; 148 Vector3 nextPosition = nextPos - center; 149 150 // 計算direction、right、up向量(注:Unity3d中使用左手座標系) 151 Vector3 direction = (nextPosition - position).normalized;//z軸 152 Vector3 right = Vector3.Cross(Vector3.up, direction).normalized;//x軸,右 153 Vector3 up = Vector3.Cross(direction, right).normalized;//x和z獲得up 154 // 設起點圓定點數據 155 SetSectionVertexData(position, direction, up, right, uvPosU); 156 } 157 158 /// <summary> 159 /// 設置終點圓頂點數據 160 /// </summary> 161 /// <param name="endPos">終點座標</param> 162 /// <param name="previousPos">上一點座標</param> 163 private void SetEndVertexData(Vector3 endPos, Vector3 previousPos) 164 { 165 // 首先計算導線點相對場景中心點的偏移座標 166 Vector3 position = endPos - center; 167 Vector3 PreviousPosition = previousPos - center; 168 169 // 計算direction、right、up向量(注:Unity3d中使用左手座標系) 170 Vector3 direction = (position - PreviousPosition).normalized;//指向下一點(結束)方向向量 171 Vector3 right = Vector3.Cross(Vector3.up, direction).normalized; 172 Vector3 up = Vector3.Cross(direction, right).normalized; 173 //計算U值 174 uvPosU += (GetPointDistance(position, PreviousPosition) / textureSizeL); 175 SetSectionVertexData(position, direction, up, right, uvPosU); 176 } 177 178 /// <summary> 179 /// 設置斷面頂點數據 180 /// </summary> 181 /// <param name="currentPos">當前點座標</param> 182 /// <param name="direction">朝向</param> 183 private void SetSectionVertexData(Vector3 currentPos, Vector3 direction, Vector3 up, Vector3 right, float u) 184 { 185 // 構建旋轉矩陣 186 Matrix4x4 m = Utils.MakeBasis(right, up, direction); 187 int baseValue = 2; 188 for (float i = 0f; i < 360.0f; i += 36.0f) 189 { 190 // 計算頂點 191 float rad = Mathf.Deg2Rad * i; 192 Vector3 targetPos = currentPos + m.MultiplyPoint3x4(new Vector3(Mathf.Cos(rad) * radius, Mathf.Sin(rad) * radius, 0.0f)); 193 // 計算V座標 194 float v = ((baseValue * 36.0f) / 360.0f); 195 // 保存頂點座標&紋理座標 196 vertices.Add(targetPos); 197 uvs.Add(new Vector2(u, v)); 198 if (i > 108) 199 { 200 baseValue -= 2; 201 } 202 else 203 { 204 baseValue += 2; 205 } 206 } 207 } 208 209 /// <summary> 210 /// 設置中間點頂點數據 211 /// </summary> 212 /// <param name="currentPos"></param> 213 /// <param name="prevPos"></param> 214 /// <param name="nextPos"></param> 215 private void SetPrepareVertexData(Vector3 currentPos, Vector3 prevPos, Vector3 nextPos) 216 { 217 // 首先計算導線點相對場景中心點的偏移座標 218 Vector3 prevPosition = prevPos - center; 219 Vector3 position = currentPos - center; 220 Vector3 anitherposition = nextPos - center; 221 222 // 計算前一段巷道的direction、right、up向量(注:Unity3d中使用左手座標系) 223 Vector3 prevDirection = (position - prevPosition).normalized; 224 Vector3 prevRight = Vector3.Cross(Vector3.up, prevDirection).normalized; 225 Vector3 prevUp = Vector3.Cross(prevDirection, prevRight).normalized; 226 227 // 計算後一段巷道的direction、right、up向量(注:Unity3d中使用左手座標系) 228 Vector3 anitherDirection = (anitherposition - position).normalized; 229 Vector3 anitherlRight = Vector3.Cross(Vector3.up, anitherDirection).normalized; 230 Vector3 anitherUp = Vector3.Cross(anitherDirection, anitherlRight).normalized; 231 232 float angle = Vector3.Angle(-prevDirection, anitherDirection); 233 234 if (angle >= 179.0) 235 { 236 //生成斷面數據不倒角處理 237 uvPosU += (GetPointDistance(position, prevPosition) / textureSizeL); 238 SetSectionVertexData(position, prevDirection, prevUp, prevRight, uvPosU); 239 return; 240 } 241 //倒角處理 242 243 //先後兩段風筒長度 244 float PrevLength = Vector3.Distance(position, prevPosition); 245 float anithorLength = Vector3.Distance(position, anitherposition); 246 247 indentationValue = PrevLength > anithorLength ? (anithorLength * 0.25f) : (PrevLength * 0.25f);//縮進爲短風筒的1/4 248 249 // 計算縮進後的位置 250 Vector3 prevEnd = position - prevDirection * indentationValue;//左 251 Vector3 behindStart = position + anitherDirection * indentationValue;// 右 252 253 uvPosU += (GetPointDistance(prevPosition, prevEnd) / textureSizeL); 254 // 生成前段結束斷面頂點數據 255 SetSectionVertexData(prevEnd, prevDirection, prevUp, prevRight, uvPosU); 256 257 // 生成中間倒角斷面頂點數據 258 //插值0-1 259 float timer = 0.1f; 260 Vector3 prevpos = prevEnd; 261 for (float i = 1.0f; i <= 9.0f; i++) 262 { 263 Vector3 pos = Utils.CalculateCubicBezierPoint(timer, prevEnd, position, behindStart); 264 // 計算斷面方向 265 Vector3 direction = (pos - prevpos).normalized; 266 Vector3 right = Vector3.Cross(Vector3.up, direction).normalized; 267 Vector3 up = Vector3.Cross(direction, right).normalized; 268 uvPosU += (GetPointDistance(pos, prevpos) / textureSizeL); 269 // 生成斷面頂點數據 270 SetSectionVertexData(pos, direction, up, right, uvPosU); 271 //遞增插值時間 272 timer += 0.1f; 273 //更新前一個點座標 274 prevpos = pos; 275 } 276 // 生成後段起始斷面頂點數據 277 SetSectionVertexData(behindStart, anitherDirection, anitherUp, anitherlRight, ++uvPosU); 278 } 279 280 /// <summary> 281 /// 設置索引數據 282 /// </summary> 283 private void SetIndexData() 284 { 285 int faceCount = (vertices.Count / devide) - 1; 286 int baseValue; 287 for (int i = 0; i < faceCount; i++) 288 { 289 baseValue = 0; 290 for (int j = 1; j <= 10; j++) 291 { 292 if (j < 10) 293 { 294 triangles.Add(i * 10 + baseValue); 295 triangles.Add(i * 10 + 11 + baseValue); 296 triangles.Add(i * 10 + baseValue + 10); 297 298 triangles.Add(i * 10 + baseValue); 299 triangles.Add(i * 10 + baseValue + 1); 300 triangles.Add(i * 10 + 11 + baseValue); 301 } 302 else 303 { 304 triangles.Add(i * 10 + baseValue); 305 triangles.Add(i * 10 + 10); 306 triangles.Add(i * 10 + baseValue + 10); 307 308 triangles.Add(i * 10 + baseValue); 309 triangles.Add(i * 10); 310 triangles.Add(i * 10 + 10); 311 } 312 baseValue++; 313 } 314 } 315 } 316 317 /// <summary> 318 /// 求兩點距離 319 /// </summary> 320 /// <param name="prevPos">前一點座標</param> 321 /// <param name="nextPos">後一點座標</param> 322 /// <returns></returns> 323 private float GetPointDistance(Vector3 prevPos, Vector3 nextPos) 324 { 325 return Vector3.Distance(prevPos, nextPos); 326 } 327 328 #endregion 329 } 330 }
這裏定了五個測試點,
到這基本結束了,可是這期間計算思考過程仍是仍是有點東西的,這玩意也是會的不難難的不會,作過一次了就好辦了,這裏給沒搞過的小朋友啓發一下。
渴望指正交流。