【转载】在Unity编辑器中创建圆锥体(不借助3DS MAX或Maya等建模工具,创建几何体)
我的注:生成几何体的主要思路是在自建mesh中设置顶点、UV坐标、三角形等信息
以下转自:http://wiki.unity3d.com/index.php?title=CreateCone
CreateCone
Author: Wolfram Kresse
Description
This editor script creates a cone with the specified tessellation (=number of vertices), top radius, bottom radius, and length. With top radius == bottom radius, the result is a cylinder. With none of the radii == 0, the result is a truncated cone. So far the resulting cone has no end caps, but you can create caps on your own by using a cone with one radius==0 and length==0.
The resulting mesh will be added as an asset to Assets/Editor, so it can be used in prefabs etc.
Note it is inevitable that a true cone (one of the radii == 0) cannot be rendered completely smooth, and will show facetting artifacts.
Usage
Place this script as "CreateCone.cs" in YourProject/Assets/Editor and a menu item will automatically appear in the "GameObject/Create Other" menu after it is compiled.
Num Vertices is the number of vertices each end will have.
Radius Top is the radius at the top. The center point will be located at (0/0/0).
Radius Bottom is the radius at the bottom. The center point will be located at (0/0/Length).
Length is the number of world units long the plane will be (+Z direction).
Opening Angle If this is >0, the top radius is set to 0, and the bottom radius is computed depending on the length, so that the given opening angle is created.
Outside defines whether the outside is visible (default).
Inside defines whether the inside is visible. Set both outside and inside to create a double-sided primitive.
Add Collider creates a matching mesh collider for the cone if checked.
C# - CreateCone.cs
1 using UnityEngine; 2 using UnityEditor; 3 using System.Collections; 4 5 // an Editor method to create a cone primitive (so far no end caps) 6 // the top center is placed at (0/0/0) 7 // the bottom center is placed at (0/0/length) 8 // if either one of the radii is 0, the result will be a cone, otherwise a truncated cone 9 // note you will get inevitable breaks in the smooth shading at cone tips 10 // note the resulting mesh will be created as an asset in Assets/Editor 11 // Author: Wolfram Kresse 12 public class CreateCone : ScriptableWizard { 13 14 public int numVertices = 10; 15 public float radiusTop = 0f; 16 public float radiusBottom = 1f; 17 public float length = 1f; 18 public float openingAngle = 0f; // if >0, create a cone with this angle by setting radiusTop to 0, and adjust radiusBottom according to length; 19 public bool outside = true; 20 public bool inside = false; 21 public bool addCollider = false; 22 23 [MenuItem ("GameObject/Create Other/Cone")] 24 static void CreateWizard() 25 { 26 ScriptableWizard.DisplayWizard("Create Cone", typeof(CreateCone)); 27 } 28 29 void OnWizardCreate(){ 30 GameObject newCone=new GameObject("Cone"); 31 if(openingAngle>0&&openingAngle<180){ 32 radiusTop=0; 33 radiusBottom=length*Mathf.Tan(openingAngle*Mathf.Deg2Rad/2); 34 } 35 string meshName = newCone.name + numVertices + "v" + radiusTop + "t" + radiusBottom + "b" + length + "l" + length + (outside?"o":"") + (inside?"i":""); 36 string meshPrefabPath = "Assets/Editor/" + meshName + ".asset"; 37 Mesh mesh = (Mesh)AssetDatabase.LoadAssetAtPath(meshPrefabPath, typeof(Mesh)); 38 if(mesh==null){ 39 mesh=new Mesh(); 40 mesh.name=meshName; 41 // can't access Camera.current 42 //newCone.transform.position = Camera.current.transform.position + Camera.current.transform.forward * 5.0f; 43 int multiplier=(outside?1:0)+(inside?1:0); 44 int offset=(outside&&inside?2*numVertices:0); 45 Vector3[] vertices=new Vector3[2*multiplier*numVertices]; // 0..n-1: top, n..2n-1: bottom 46 Vector3[] normals=new Vector3[2*multiplier*numVertices]; 47 Vector2[] uvs=new Vector2[2*multiplier*numVertices]; 48 int[] tris; 49 float slope=Mathf.Atan((radiusBottom-radiusTop)/length); // (rad difference)/height 50 float slopeSin=Mathf.Sin(slope); 51 float slopeCos=Mathf.Cos(slope); 52 int i; 53 54 for(i=0;i<numVertices;i++){ 55 float angle=2*Mathf.PI*i/numVertices; 56 float angleSin=Mathf.Sin(angle); 57 float angleCos=Mathf.Cos(angle); 58 float angleHalf=2*Mathf.PI*(i+0.5f)/numVertices; // for degenerated normals at cone tips 59 float angleHalfSin=Mathf.Sin(angleHalf); 60 float angleHalfCos=Mathf.Cos(angleHalf); 61 62 vertices[i]=new Vector3(radiusTop*angleCos,radiusTop*angleSin,0); 63 vertices[i+numVertices]=new Vector3(radiusBottom*angleCos,radiusBottom*angleSin,length); 64 65 if(radiusTop==0) 66 normals[i]=new Vector3(angleHalfCos*slopeCos,angleHalfSin*slopeCos,-slopeSin); 67 else 68 normals[i]=new Vector3(angleCos*slopeCos,angleSin*slopeCos,-slopeSin); 69 if(radiusBottom==0) 70 normals[i+numVertices]=new Vector3(angleHalfCos*slopeCos,angleHalfSin*slopeCos,-slopeSin); 71 else 72 normals[i+numVertices]=new Vector3(angleCos*slopeCos,angleSin*slopeCos,-slopeSin); 73 74 uvs[i]=new Vector2(1.0f*i/numVertices,1); 75 uvs[i+numVertices]=new Vector2(1.0f*i/numVertices,0); 76 77 if(outside&&inside){ 78 // vertices and uvs are identical on inside and outside, so just copy 79 vertices[i+2*numVertices]=vertices[i]; 80 vertices[i+3*numVertices]=vertices[i+numVertices]; 81 uvs[i+2*numVertices]=uvs[i]; 82 uvs[i+3*numVertices]=uvs[i+numVertices]; 83 } 84 if(inside){ 85 // invert normals 86 normals[i+offset]=-normals[i]; 87 normals[i+numVertices+offset]=-normals[i+numVertices]; 88 } 89 } 90 mesh.vertices = vertices; 91 mesh.normals = normals; 92 mesh.uv = uvs; 93 94 // create triangles 95 // here we need to take care of point order, depending on inside and outside 96 int cnt=0; 97 if(radiusTop==0){ 98 // top cone 99 tris=new int[numVertices*3*multiplier]; 100 if(outside) 101 for(i=0;i<numVertices;i++){ 102 tris[cnt++]=i+numVertices; 103 tris[cnt++]=i; 104 if(i==numVertices-1) 105 tris[cnt++]=numVertices; 106 else 107 tris[cnt++]=i+1+numVertices; 108 } 109 if(inside) 110 for(i=offset;i<numVertices+offset;i++){ 111 tris[cnt++]=i; 112 tris[cnt++]=i+numVertices; 113 if(i==numVertices-1+offset) 114 tris[cnt++]=numVertices+offset; 115 else 116 tris[cnt++]=i+1+numVertices; 117 } 118 }else if(radiusBottom==0){ 119 // bottom cone 120 tris=new int[numVertices*3*multiplier]; 121 if(outside) 122 for(i=0;i<numVertices;i++){ 123 tris[cnt++]=i; 124 if(i==numVertices-1) 125 tris[cnt++]=0; 126 else 127 tris[cnt++]=i+1; 128 tris[cnt++]=i+numVertices; 129 } 130 if(inside) 131 for(i=offset;i<numVertices+offset;i++){ 132 if(i==numVertices-1+offset) 133 tris[cnt++]=offset; 134 else 135 tris[cnt++]=i+1; 136 tris[cnt++]=i; 137 tris[cnt++]=i+numVertices; 138 } 139 }else{ 140 // truncated cone 141 tris=new int[numVertices*6*multiplier]; 142 if(outside) 143 for(i=0;i<numVertices;i++){ 144 int ip1=i+1; 145 if(ip1==numVertices) 146 ip1=0; 147 148 tris[cnt++]=i; 149 tris[cnt++]=ip1; 150 tris[cnt++]=i+numVertices; 151 152 tris[cnt++]=ip1+numVertices; 153 tris[cnt++]=i+numVertices; 154 tris[cnt++]=ip1; 155 } 156 if(inside) 157 for(i=offset;i<numVertices+offset;i++){ 158 int ip1=i+1; 159 if(ip1==numVertices+offset) 160 ip1=offset; 161 162 tris[cnt++]=ip1; 163 tris[cnt++]=i; 164 tris[cnt++]=i+numVertices; 165 166 tris[cnt++]=i+numVertices; 167 tris[cnt++]=ip1+numVertices; 168 tris[cnt++]=ip1; 169 } 170 } 171 mesh.triangles = tris; 172 AssetDatabase.CreateAsset(mesh, meshPrefabPath); 173 AssetDatabase.SaveAssets(); 174 } 175 176 MeshFilter mf=newCone.AddComponent<MeshFilter>(); 177 mf.mesh = mesh; 178 179 newCone.AddComponent<MeshRenderer>(); 180 181 if(addCollider){ 182 MeshCollider mc=newCone.AddComponent<MeshCollider>(); 183 mc.sharedMesh=mf.sharedMesh; 184 } 185 186 Selection.activeObject = newCone; 187 } 188 }
浙公网安备 33010602011771号