202 lines
6.0 KiB
C#
202 lines
6.0 KiB
C#
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<MeshFilter>();
|
||
|
|
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<MeshCollider>();
|
||
|
|
if(collider == null){
|
||
|
|
collider = obj.AddComponent<MeshCollider>();
|
||
|
|
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);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|