using UnityEngine; using System.Collections; [ExecuteInEditMode] public class Diaphragm : MonoBehaviour { public float OutsideDiameter = 1.0f; public float MaxAperture = 0.75f; public float MinAperture = 0.05f; public int LeafCount = 15; public float LeafDegreeLength = 140.0f; public int LeafLengthTesselation = 10; public float LeafThickness = 0.005f; public Material material; public bool DrawDebugLines = true; public bool updateInEditor = false; public float MaxLeafAngle = 50.0f; [Range(0.0f,1.0f)] public float State = 0.0f; // Use this for initialization void Start () { } // Update is called once per frame void Update () { UpdateLeafs (); } ///Vector2//Vec void UpdateLeafs(){ if (transform.childCount > LeafCount) { int cntRemove = transform.childCount - LeafCount; GameObject[] removeArray = new GameObject[cntRemove]; for (int i = 0; i < cntRemove; ++i) { removeArray [i] = transform.GetChild (i).gameObject; } foreach (GameObject go in removeArray) { go.transform.parent = null; DestroyImmediate (go); } } else { int cntAdd = LeafCount - transform.childCount; for (int i = 0; i < cntAdd; ++i) { GameObject obj = AdvancedUtils.CreateMeshObject(); obj.renderer.sharedMaterial = material; obj.transform.parent = transform; } } float jointsRadius = (OutsideDiameter * 0.5f + MaxAperture * 0.5f) * 0.5f; for (int i = 0; i < LeafCount; ++i) { float leafAngle = (360.0f / (float)LeafCount) * (float)i; GameObject go = transform.GetChild (i).gameObject; go.transform.localPosition = GetLeafPosition(i); go.transform.localRotation = Quaternion.identity; go.transform.localScale = new Vector3(1,1,1); } int leafsCount = transform.childCount; float rotation = MaxLeafAngle * State; for (int i = 0; i < leafsCount; ++i) { GameObject obj = transform.GetChild(i).gameObject; if (DrawDebugLines) { AdvancedGizmo.DrawCircle(obj.transform.position, Vector3.up, 0.02f, Color.blue, 12, false, 2); } var mf = obj.GetComponent(); Mesh m = mf.sharedMesh; float leafWidth = (OutsideDiameter - MaxAperture) * 0.5f; float leafAngularOffset = (360.0f / (float)LeafCount) * (float)i; int planeVertCnt = (LeafLengthTesselation + 1) * 2; int totalVertCnt = planeVertCnt * 4; float innerRadius = MaxAperture * 0.5f; float outerRadius = OutsideDiameter * 0.5f; Vector3 leafPosition = GetLeafPosition(i); float angleBetweenPivots = 360.0f / leafsCount; float angularElevation = LeafThickness / angleBetweenPivots; float sectionAngularLength = LeafDegreeLength / (float)LeafLengthTesselation; //generate vertices& uvs Vector3[] vertices = new Vector3[totalVertCnt]; Vector2[] uvs = new Vector2[vertices.Length]; for(int j = 0; j <= LeafLengthTesselation; ++j){ float elevation = angularElevation * sectionAngularLength * (float)j; Vector3 elevationVector = Vector3.up * - elevation; Vector3 sliceDirection = Quaternion.AngleAxis(leafAngularOffset + sectionAngularLength * (float)j, Vector3.up) * Vector3.forward; int sliceVertexOffset = j * 8; vertices[sliceVertexOffset + 0] = sliceDirection * outerRadius - leafPosition + elevationVector; vertices[sliceVertexOffset + 1] = sliceDirection * innerRadius - leafPosition + elevationVector; vertices[sliceVertexOffset + 2] = vertices[sliceVertexOffset + 1]; vertices[sliceVertexOffset + 3] = vertices[sliceVertexOffset + 1] + Vector3.up * (-LeafThickness); vertices[sliceVertexOffset + 4] = vertices[sliceVertexOffset + 3]; vertices[sliceVertexOffset + 5] = vertices[sliceVertexOffset + 0] + Vector3.up * (-LeafThickness); vertices[sliceVertexOffset + 6] = vertices[sliceVertexOffset + 5]; vertices[sliceVertexOffset + 7] = vertices[sliceVertexOffset + 0]; float u = (1.0f / (float)LeafLengthTesselation) * (float)j; for(int k = 0; k < 8; ++k){ uvs[sliceVertexOffset + k] = new Vector2(u,k%2); } } //triangulate const int trianglePerSection = 8; int totalTriangles = trianglePerSection * LeafLengthTesselation; const int indicesPerSection = trianglePerSection * 3; int totalIndices = indicesPerSection * LeafLengthTesselation; int[] indices = new int[totalIndices]; int[] sectionIndices = new int[indicesPerSection]{ 0,8,9, 0,9,1, 2,10,11, 2,11,3, 4,12,13, 4,13,5, 15,7,6, 15,6,14}; int indexOffset = 0; //triangulate per section for(int j = 0; j < LeafLengthTesselation; ++j){ int sectionVertexOffset = j * 8; for(int k = 0; k < indicesPerSection; ++k){ indices[indexOffset++] = sectionVertexOffset + sectionIndices[k]; } } //generate normals Vector3[] normals = new Vector3[vertices.Length]; for(int j = 0; j < indices.Length; j+=3){ Vector3 normal = AdvancedMath.TriangleNormal( vertices[indices[j + 0]], vertices[indices[j + 1]], vertices[indices[j + 2]]); normals[indices[j + 0]] = normal; normals[indices[j + 1]] = normal; normals[indices[j + 2]] = normal; } m.vertices = vertices; m.SetIndices(indices, MeshTopology.Triangles, 0); m.uv = uvs; m.normals = normals; MeshCollider collider = obj.GetComponent(); if(collider == null){ collider = obj.AddComponent(); collider.sharedMesh = m; } obj.transform.localRotation = Quaternion.AngleAxis(rotation, Vector3.up); } } Vector3 GetLeafPosition(int id){ float jointsRadius = (OutsideDiameter * 0.5f + MaxAperture * 0.5f) * 0.5f; float leafAngle = (360.0f / (float)LeafCount) * (float)id; return Quaternion.AngleAxis(leafAngle, Vector3.up) * Vector3.forward * jointsRadius; } void OnDrawGizmos(){ if (updateInEditor) { UpdateLeafs (); } if (DrawDebugLines) { AdvancedGizmo.DrawCircle (transform.position, Vector3.up, OutsideDiameter * 0.5f, Color.red, 36); AdvancedGizmo.DrawCircle (transform.position, Vector3.up, MaxAperture * 0.5f, Color.green, 36, false, 2); } } }