乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      [Mesh]網(wǎng)格的快速切割

       勤奮不止 2019-06-25

      最終效果




      思路

      • 確定切面
      • 根據(jù)切面將原模型頂點分為切面上下兩類
      • 將交面進行特殊處理,根據(jù)角度或距離插值運算交點,并添加頂點索引
      • 對剖面頂點進行重新排序,連接,UV映射

      實現(xiàn)

      因為代碼量大只寫局部偽代碼說明。
      關于網(wǎng)格的基礎教程,請參閱Mesh網(wǎng)格篇(一)代碼生成圓柱Mesh
      為了方便這里我們拿BOX舉例。

      頂點站隊

      當我們確定切面裁切一個box時,我們首先需要做的是把頂點分類,通過向量的點乘將頂點0145和2376分為切面的ab兩組,同時記錄下ab的頂點進入排序和他在切面上下的狀態(tài)。

      1. bool[] above = new bool[MeshInfo.vertices.Count];
      2. int[] newTriangles = new int[MeshInfo.vertices.Count];
      3. for (int i = 0; i < newTriangles.Length; i++)
      4. {
      5. Vector3 vert = MeshInfo.vertices[i];
      6. above[i] = Vector3.Dot(vert - point, normal) >= 0f;
      7. if (above[i])
      8. {
      9. newTriangles[i] = a.vertices.Count;
      10. a.Add(vert, MeshInfo.uvs[i], MeshInfo.normals[i], MeshInfo.tangents[i]);
      11. }
      12. else
      13. {
      14. newTriangles[i] = b.vertices.Count;
      15. b.Add(vert, MeshInfo.uvs[i], MeshInfo.normals[i], MeshInfo.tangents[i]);
      16. }
      17. }

      接下來我們按照原模型的連接方式逐個連接ab中的頂點

      1. for (int i = 0; i < triangleCount; i++)
      2. {
      3. int _i0 = MeshInfo.triangles[i * 3];
      4. int _i1 = MeshInfo.triangles[i * 3 + 1];
      5. int _i2 = MeshInfo.triangles[i * 3 + 2];
      6. bool _a0 = above[_i0];
      7. bool _a1 = above[_i1];
      8. bool _a2 = above[_i2];
      9. if (_a0 && _a1 && _a2)
      10. {
      11. a.triangles.Add(newTriangles[_i0]);
      12. a.triangles.Add(newTriangles[_i1]);
      13. a.triangles.Add(newTriangles[_i2]);
      14. }
      15. else if (!_a0 && !_a1 && !_a2)
      16. {
      17. b.triangles.Add(newTriangles[_i0]);
      18. b.triangles.Add(newTriangles[_i1]);
      19. b.triangles.Add(newTriangles[_i2]);
      20. }
      21. else
      22. {
      23. //....
      24. }
      通過與原模型頂點索引的比較,我們將得到

      切面補間

      這樣2個模型,很明顯中間網(wǎng)格需要我們在else中進行補點補線。

      這里講下我們如果去切割一個平面。
      一個平面被切割時,也就兩個三角面被切割。

      假如△abc被坐標軸x切割,我們如何確定點d和e的位置呢。
      求角度比scale = ∠yba/ ∠yoa;(float scale = Vector.Dot(a-o,y-o)/Vector.Dot(a-b,y-o);)
      d = b+(a-b)*scale;
      e = c+(a-c)*scale;
      然后根據(jù)網(wǎng)格的連接順序連接,aed,bdc,cde。
      然后把頂點和a頂點索引加入到a面中,頂點和b頂點索引加入到b面中。

      我們就能得到類似上面的2個模型。

      剖面填充

      這時我們就要填充剖面,但是剖面的頂點順序我們并不知道。
      所以要對頂點進行排序。

      局限性排序

      幸運的是我們的頂點都是兩兩相連,每個頂點的位置其實有2個面的頂點重疊。
      根據(jù)這個特性,我們就可以以此為根據(jù)尋找下個連接頂點的位置,然后刪除重復的頂點。
      1. for (int i = 0; i < edges.Count - 3; i++)
      2. {
      3. Vector3 t = edges[i + 1];
      4. Vector3 temp = edges[i + 3];
      5. for (int j = i + 2; j < edges.Count - 1; j += 2)
      6. {
      7. if ((edges[j] - t).sqrMagnitude < 1e-6)
      8. {
      9. edges[j] = edges[i + 2];
      10. edges[i + 3] = edges[j + 1];
      11. edges[j + 1] = temp;
      12. break;
      13. }
      14. if ((edges[j + 1] - t).sqrMagnitude < 1e-6)
      15. {
      16. edges[j + 1] = edges[i + 2];
      17. edges[i + 3] = edges[j];
      18. edges[j] = temp;
      19. break;
      20. }
      21. }
      22. edges.RemoveAt(i + 2);
      23. }
      24. edges.RemoveAt(edges.Count - 1);
      這樣我們就得到了一個按剖面形狀連接的順序頂點。
      只要按012,023,034。。。。的順序連接下去就能把剖面填充。

      常規(guī)排序

      那如何對凸多邊形上內任意若干的頂點進行連接呢。
      這時候我們需要根據(jù)凸多邊形的外切線和角度來確定下個頂點的位置。
      這里只提供思路,代碼太長就不貼了,而且在模型切割上效率不如上面的高。
      首先將頂點都轉換到切線尋找凸多邊形的外切線向量。
      然后逐頂點對比角度。
      如果兩個頂點與切線共線,我們就比較距離,一個頂點只有2個頂點連接他。第一次共線距離為近的排序,第二次共線距離為遠的排序。

      凹多邊形

      有人問凹多邊形如何填充,呵呵,如果填充凹多邊形,要先把凹多邊形分割成若干個凸多邊形進行填充。

      UV映射

      接下來就是對剖面的頂點UV進行映射。根據(jù)情況賦值的方法不同。
      拿BOX舉例,
      我們需要把box的bound的size傳入,然后根據(jù) point/size 來確定uv偏移值,根據(jù)切面的法線方向決定取xy?xz?zy?
      1. int count = triangles.Count / 3;
      2. for (int i = 0; i < count; i++)
      3. {
      4. int _i0 = triangles[i * 3];
      5. int _i1 = triangles[i * 3 + 1];
      6. int _i2 = triangles[i * 3 + 2];
      7. Vector3 v0 = vertices[_i0] - center + size / 2f;
      8. Vector3 v1 = vertices[_i1] - center + size / 2f;
      9. Vector3 v2 = vertices[_i2] - center + size / 2f;
      10. v0 = new Vector3(v0.x / size.x, v0.y / size.y, v0.z / size.z);
      11. v1 = new Vector3(v1.x / size.x, v1.y / size.y, v1.z / size.z);
      12. v2 = new Vector3(v2.x / size.x, v2.y / size.y, v2.z / size.z);
      13. Vector3 a = v0 - v1;
      14. Vector3 b = v2 - v1;
      15. Vector3 dir = Vector3.Cross(a, b);
      16. float x = Mathf.Abs(Vector3.Dot(dir, Vector3.right));
      17. float y = Mathf.Abs(Vector3.Dot(dir, Vector3.up));
      18. float z = Mathf.Abs(Vector3.Dot(dir, Vector3.forward));
      19. if (x > y && x > z)
      20. {
      21. uvs[_i0] = new Vector2(v0.z, v0.y);
      22. uvs[_i1] = new Vector2(v1.z, v1.y);
      23. uvs[_i2] = new Vector2(v2.z, v2.y);
      24. }
      25. else if (y > x && y > z)
      26. {
      27. uvs[_i0] = new Vector2(v0.x, v0.z);
      28. uvs[_i1] = new Vector2(v1.x, v1.z);
      29. uvs[_i2] = new Vector2(v2.x, v2.z);
      30. }
      31. else if (z > x && z > y)
      32. {
      33. uvs[_i0] = new Vector2(v0.x, v0.y);
      34. uvs[_i1] = new Vector2(v1.x, v1.y);
      35. uvs[_i2] = new Vector2(v2.x, v2.y);
      36. }
      37. }

        本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多