您好,登錄后才能下訂單哦!
看到這篇文章你可能好奇unity自帶圓柱體組件,直接就可以生成,為什么我們還要用代碼生成。其實是最近領導對項目有一個要求,就是我們要在自寫編輯器內操作圓管,也就是圓柱體。功能類似3DMax里的拉伸管線。剛開始看到這個要求我內心是拒絕的,mmp我是unity程序員不是圖像學程序員啊,這看著有點底層啊。但是心想,這也是自我學習提升的機會,于是我就給領導個面子將它實現吧。我們知道如果想像3Dmax里那樣操作管線,就必須用代碼創建圓柱體并用代碼控制他的頂點位置才能實現我們的需求。所以第一步就是用代碼創建我們需要的圓柱體。實現的效果如下:
其實之前我自己嘗試了解創建立方體的代碼,看著很簡單,其實也不簡單,主要是對頂點,以及對應組成三角面頂點順序的設置。我在網上搜到一篇自寫圓柱體的代碼,看著不錯,直接復制來了,但是他提供的少兩個面。所以需要我們自己去補上這個面。然后很重要的一點是兩個面的交點不可以共用,必須再添加一次,因為涉及到法線的問題。
//圓柱體是由兩個圓和一個長方形組成的 先輸入長方形的頂點 然后在輸入圓頂點 private void UpdateMesh(Mesh mesh,int edg_x, int edg_y, float rad, float len) { edg_x = Mathf.Max(2, edg_x);//保證最低2個邊 edg_y = Mathf.Max(2, edg_y); int _deglen = (edg_x +1)*edg_y;//長方體 int totalcount = _deglen + (1 + edg_x + 1) * 2; //加兩個圓 Vector3[] normals = new Vector3[totalcount]; Vector3[] verts = new Vector3[totalcount]; Vector2[] uvs = new Vector2[totalcount]; int[] trians = new int[edg_x * edg_y*6]; float reg = 6.28318f / edg_x; float _len = len / (edg_y - 1); for (int y = 0; y < edg_y; y++) for (int x = 0; x < edg_x + 1; x++)//多一個邊來保存UV值 { int i = x + y * (edg_x + 1); verts[i] = new Vector3(Mathf.Sin((reg * (x % edg_x)) % 6.28318f) * rad, Mathf.Cos((reg * (x % edg_x)) % 6.28318f) * rad, rightPos + y * _len);//計算頂點坐標 normals[i] = new Vector3(verts[i].x, verts[i].y, 0);//計算法線方向 int id = x % (edg_x + 1) * 6 + y * edg_x * 6; if (x < edg_x + 1 && y < edg_y - 1 && (id + 5) < trians.Length)//計算頂點數組 { if(length>0) { trians[id] = i; trians[id + 1] = trians[id + 4] = i + edg_x + 1; trians[id + 2] = trians[id + 3] = i + 1; trians[id + 5] = i + edg_x + 2; } else { trians[id] = i; trians[id + 1] = trians[id + 3] = i + 1; trians[id + 2]= trians[id + 5]=i + edg_x + 1; trians[id + 4] = i + edg_x + 2; } } //if (edg_x != 2)//計算UV,考慮到2個邊的情況 // uvs[i] = new Vector2(x == edg_x ? 1f : quaduvStep.x * x, y == edg_y - 1 ? (2*rad+len)/totalLen : quaduvStep.y * y); //else // uvs[i] = new Vector2(x % edg_x, y == edg_y - 1 ? (2 * rad + len) / totalLen : quaduvStep.y * y); } int maxId = edg_x * (edg_y - 1) * 6; verts[_deglen] = new Vector3(0,0,rightPos); normals[_deglen] = -Vector3.forward; //uvs[_deglen] = new Vector2(0.5f, (rad) / totalLen); //原點一面 for (int x = 0; x < edg_x+1 ; x++) { verts[_deglen + 1 + x] = new Vector3(Mathf.Sin((reg * (x % edg_x)) % 6.28318f) * rad, Mathf.Cos((reg * (x % edg_x)) % 6.28318f) * rad, rightPos); normals[_deglen + 1 + x] = -Vector3.forward; if (x == edg_x) continue; if(length>0) { trians[3 * x + maxId] = _deglen; trians[3 * x + 1 + maxId] = _deglen + 1 + x; trians[3 * x + 2 + maxId] = _deglen + 2 + x; } else { trians[3 * x + maxId] = _deglen; trians[3 * x + 1 + maxId] = _deglen + 2 + x; trians[3 * x + 2 + maxId] = _deglen + 1 + x; } } //遠點一面 maxId += 3 * edg_x; verts[_deglen + 2 + edg_x] = new Vector3(0, 0, leftPos); normals[_deglen + 2 + edg_x] = Vector3.forward; //uvs[_deglen + 1] = new Vector2(0.5f, (3 * rad + len) / totalLen); for (int x = 0; x < edg_x+1; x++) { verts[1 + x+edg_x+2+ _deglen] =new Vector3(Mathf.Sin((reg * (x % edg_x)) % 6.28318f) * rad, Mathf.Cos((reg * (x % edg_x)) % 6.28318f) * rad,leftPos); normals[1 + x + edg_x + 2 + _deglen] = Vector3.forward; if (x == edg_x) continue; if (length > 0) { trians[3 * x + maxId] = _deglen + 2 + edg_x; trians[3 * x + 1 + maxId] = _deglen + 2 + edg_x + x + 2; trians[3 * x + 2 + maxId] = _deglen + 2 + edg_x + x + 1; } else { trians[3 * x + maxId] = _deglen + 2 + edg_x; trians[3 * x + 1 + maxId] = _deglen + 2 + edg_x + x + 1; trians[3 * x + 2 + maxId] = _deglen + 2 + edg_x + x + 2; } } mesh.Clear(); mesh.vertices = verts; mesh.triangles = trians; //mesh.uv = uvs; mesh.normals = normals; mesh.RecalculateBounds(); }
其實看代碼會發現這個圓柱體的長度len是由我們自己聲明的變量leftPos-rightPos獲得的。即length=len=leftPos-rightPos。我們可以操作變量leftPos和rightPos來控制圓柱一端的位置以及其長度。當我們length<0的時候,他的三角面頂點繪制順序正好相反,所以需要在代碼塊中判斷下。以上就是對代碼繪制圓柱體的實現。希望對你有幫助。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。