public void StartGrow() { if (IvyRoot.transform.parent == null) { return; } m_DoNotDrawGizmos = false; Mesh _mesh = IvyRoot.transform.parent.GetComponent <MeshFilter>().sharedMesh; Vector3[] _vertices = _mesh.vertices; Vector2[] _UVs = _mesh.uv; Vector3[] _normals = _mesh.normals; int[] _triangles = _mesh.triangles; //Debug.Log(_vertices.Length + " " + _UVs.Length + " " + _normals.Length + " " + _triangles.Length); for (int i = 0; i < _mesh.vertexCount; i++) { SceneObjMesh.vertices.Add(new BasicVertex(_vertices[i])); } if (_mesh.normals.Length > 0) { for (int j = 0; j < _mesh.normals.Length; j++) { SceneObjMesh.normals.Add(new BasicNormal(_normals[j])); } } else { for (int j = 0; j < _mesh.vertexCount; j++) { SceneObjMesh.normals.Add(new BasicNormal()); } } if (_mesh.uv.Length > 0) { for (int k = 0; k < _mesh.uv.Length; k++) { SceneObjMesh.texCoords.Add(new BasicTexCoord(_UVs[k])); } } else { for (int k = 0; k < _mesh.vertexCount; k++) { SceneObjMesh.texCoords.Add(new BasicTexCoord()); } } for (int t = 0; t < _triangles.Length / 3; t++) { BasicTriangle temptri = new BasicTriangle(); temptri.v0id = (uint)_triangles[t * 3] + 1; temptri.v1id = (uint)_triangles[t * 3 + 1] + 1; temptri.v2id = (uint)_triangles[t * 3 + 2] + 1; temptri.n0id = (uint)_triangles[t * 3] + 1; temptri.n1id = (uint)_triangles[t * 3 + 1] + 1; temptri.n2id = (uint)_triangles[t * 3 + 2] + 1; temptri.t0id = (uint)_triangles[t * 3] + 1; temptri.t1id = (uint)_triangles[t * 3 + 1] + 1; temptri.t2id = (uint)_triangles[t * 3 + 2] + 1; SceneObjMesh.triangles.Add(temptri); } SceneObjMesh.prepareData(); SceneObjMesh.calculateVertexNormals(); SceneObjMesh.prepareData(); }
/** creates the ivy triangle mesh */ public void birth() { //evolve a gaussian filter over the adhesian vectors float [] gaussian = { 1.0f, 2.0f, 4.0f, 7.0f, 9.0f, 10.0f, 9.0f, 7.0f, 4.0f, 2.0f, 1.0f }; foreach (var root in roots) { for (int g = 0; g < 5; ++g) { for (int node = 0; node < root.nodes.Count; node++) { Vector3 e = Vector3.zero; for (int i = -5; i <= 5; ++i) { Vector3 tmpAdhesion = Vector3.zero; if ((node + i) < 0) { tmpAdhesion = root.nodes[0].adhesionVector; } if ((node + i) >= root.nodes.Count) { tmpAdhesion = root.nodes[root.nodes.Count - 1].adhesionVector; } if (((node + i) >= 0) && ((node + i) < root.nodes.Count)) { tmpAdhesion = root.nodes[node + i].adhesionVector; } e += tmpAdhesion * gaussian[i + 5]; } root.nodes[node].smoothAdhesionVector = e / 56.0f; } foreach (var _node in root.nodes) { _node.adhesionVector = _node.smoothAdhesionVector; } } } //parameters that depend on the scene object bounding sphere float local_ivyLeafSize = IvyManager.SceneObjMesh.boundingSphereRadius * ivySize * ivyLeafSize; float local_ivyBranchSize = IvyManager.SceneObjMesh.boundingSphereRadius * ivySize * ivyBranchSize; //reset existing geometry reset(); //set data path path = "../textures/"; //create material for leafs BasicMaterial tmpMaterial = new BasicMaterial(); tmpMaterial.id = 1; tmpMaterial.name = "leaf_adult"; tmpMaterial.texFile = IvyManager.LeafAdultTexPathName; materials.Add(tmpMaterial); //create second material for leafs tmpMaterial = new BasicMaterial(); tmpMaterial.id = 2; tmpMaterial.name = "leaf_young"; tmpMaterial.texFile = IvyManager.LeafYoungTexPathName; materials.Add(tmpMaterial); //create material for branches tmpMaterial = new BasicMaterial(); tmpMaterial.id = 3; tmpMaterial.name = "branch"; tmpMaterial.texFile = IvyManager.branchTexPathName; materials.Add(tmpMaterial); //create leafs foreach (var root in roots) { //simple multiplier, just to make it a more dense for (int i = 0; i < 10; ++i) { //srand(i + (root - roots.begin()) * 10); foreach (var node in root.nodes) { IvyNode back_node = root.nodes[root.nodes.Count - 1]; //weight depending on ratio of node length to total length float weight = Mathf.Pow(node.length / back_node.length, 0.7f); //test: the probability of leaves on the ground is increased float groundIvy = Mathf.Max(0.0f, -Vector3.Dot(new Vector3(0.0f, 1.0f, 0.0f), node.adhesionVector.normalized)); weight += groundIvy * Mathf.Pow(1.0f - node.length / back_node.length, 2.0f); //random influence float probability = Random.value; if (probability * weight > leafProbability) { //alignment weight depends on the adhesion "strength" float alignmentWeight = node.adhesionVector.magnitude; //horizontal angle (+ an epsilon vector, otherwise there's a problem at 0?and 90?.. mmmh) float phi = vector2ToPolar(new Vector2(node.adhesionVector.z, node.adhesionVector.x).normalized + new Vector2(Vector2.kEpsilon, Vector2.kEpsilon)) - Mathf.PI * 0.5f; //vertical angle, trimmed by 0.5 float theta = Vector3.Angle(node.adhesionVector, new Vector3(0.0f, -1.0f, 0.0f)) * 0.5f; //center of leaf quad Vector3 center = node.pos + new Vector3(Random.Range(-0.5f, 0.5f), Random.Range(-0.5f, 0.5f), Random.Range(-0.5f, 0.5f)).normalized *local_ivyLeafSize; //size of leaf float sizeWeight = 1.5f - (Mathf.Cos(weight * 2.0f * Mathf.PI) * 0.5f + 0.5f); //random influence phi += Random.Range(-0.5f, 0.5f) * (1.3f - alignmentWeight); theta += Random.Range(-0.5f, 0.5f) * (1.1f - alignmentWeight); //create vertices BasicVertex tmpVertex = new BasicVertex(); tmpVertex.pos = center + new Vector3(-local_ivyLeafSize * sizeWeight, 0.0f, local_ivyLeafSize * sizeWeight); tmpVertex.pos = rotateAroundAxis(tmpVertex.pos, center, new Vector3(0.0f, 0.0f, 1.0f), theta); tmpVertex.pos = rotateAroundAxis(tmpVertex.pos, center, new Vector3(0.0f, 1.0f, 0.0f), phi); tmpVertex.pos += new Vector3(Random.Range(-0.5f, 0.5f), Random.Range(-0.5f, 0.5f), Random.Range(-0.5f, 0.5f)).normalized *local_ivyLeafSize *sizeWeight * 0.5f; vertices.Add(tmpVertex); tmpVertex = new BasicVertex(); tmpVertex.pos = center + new Vector3(local_ivyLeafSize * sizeWeight, 0.0f, local_ivyLeafSize * sizeWeight); tmpVertex.pos = rotateAroundAxis(tmpVertex.pos, center, new Vector3(0.0f, 0.0f, 1.0f), theta); tmpVertex.pos = rotateAroundAxis(tmpVertex.pos, center, new Vector3(0.0f, 1.0f, 0.0f), phi); tmpVertex.pos += new Vector3(Random.Range(-0.5f, 0.5f), Random.Range(-0.5f, 0.5f), Random.Range(-0.5f, 0.5f)).normalized *local_ivyLeafSize *sizeWeight * 0.5f; vertices.Add(tmpVertex); tmpVertex = new BasicVertex(); tmpVertex.pos = center + new Vector3(-local_ivyLeafSize * sizeWeight, 0.0f, -local_ivyLeafSize * sizeWeight); tmpVertex.pos = rotateAroundAxis(tmpVertex.pos, center, new Vector3(0.0f, 0.0f, 1.0f), theta); tmpVertex.pos = rotateAroundAxis(tmpVertex.pos, center, new Vector3(0.0f, 1.0f, 0.0f), phi); tmpVertex.pos += new Vector3(Random.Range(-0.5f, 0.5f), Random.Range(-0.5f, 0.5f), Random.Range(-0.5f, 0.5f)).normalized *local_ivyLeafSize *sizeWeight * 0.5f; vertices.Add(tmpVertex); tmpVertex = new BasicVertex(); tmpVertex.pos = center + new Vector3(local_ivyLeafSize * sizeWeight, 0.0f, -local_ivyLeafSize * sizeWeight); tmpVertex.pos = rotateAroundAxis(tmpVertex.pos, center, new Vector3(0.0f, 0.0f, 1.0f), theta); tmpVertex.pos = rotateAroundAxis(tmpVertex.pos, center, new Vector3(0.0f, 1.0f, 0.0f), phi); tmpVertex.pos += new Vector3(Random.Range(-0.5f, 0.5f), Random.Range(-0.5f, 0.5f), Random.Range(-0.5f, 0.5f)).normalized *local_ivyLeafSize *sizeWeight * 0.5f; vertices.Add(tmpVertex); //create texCoords BasicTexCoord tmpTexCoord = new BasicTexCoord(); tmpTexCoord.uv = new Vector2(0.0f, 1.0f); texCoords.Add(tmpTexCoord); tmpTexCoord = new BasicTexCoord(); tmpTexCoord.uv = new Vector2(1.0f, 1.0f); texCoords.Add(tmpTexCoord); tmpTexCoord = new BasicTexCoord(); tmpTexCoord.uv = new Vector2(0.0f, 0.0f); texCoords.Add(tmpTexCoord); tmpTexCoord = new BasicTexCoord(); tmpTexCoord.uv = new Vector2(1.0f, 0.0f); texCoords.Add(tmpTexCoord); //create triangle BasicTriangle tmpTriangle = new BasicTriangle(); tmpTriangle.matid = 1; float _probability = Random.value; if (_probability * weight > leafProbability) { tmpTriangle.matid = 2; } tmpTriangle.v0id = (uint)vertices.Count - 1; tmpTriangle.v1id = (uint)vertices.Count - 3; tmpTriangle.v2id = (uint)vertices.Count - 2; tmpTriangle.t0id = (uint)vertices.Count - 1; tmpTriangle.t1id = (uint)vertices.Count - 3; tmpTriangle.t2id = (uint)vertices.Count - 2; triangles.Add(tmpTriangle); BasicTriangle tmpTriangle2 = new BasicTriangle(); tmpTriangle2.matid = tmpTriangle.matid; tmpTriangle2.v0id = (uint)vertices.Count - 2; tmpTriangle2.v1id = (uint)vertices.Count - 0; tmpTriangle2.v2id = (uint)vertices.Count - 1; tmpTriangle2.t0id = (uint)vertices.Count - 2; tmpTriangle2.t1id = (uint)vertices.Count - 0; tmpTriangle2.t2id = (uint)vertices.Count - 1; triangles.Add(tmpTriangle2); } } } } //branches foreach (var root in roots) { //process only roots with more than one node if (root.nodes.Count == 1) { continue; } //branch diameter depends on number of parents float local_ivyBranchDiameter = 1.0f / (float)(root.parents + 1) + 1.0f; for (int node = 0; node < root.nodes.Count - 1; node++) { //weight depending on ratio of node length to total length float weight = root.nodes[node].length / root.nodes[root.nodes.Count - 1].length; //create trihedral vertices Vector3 up = new Vector3(0.0f, -1.0f, 0.0f); Vector3 basis = (root.nodes[node + 1].pos - root.nodes[node].pos).normalized; Vector3 b0 = Vector3.Cross(up, basis).normalized *local_ivyBranchDiameter *local_ivyBranchSize *(1.3f - weight) + root.nodes[node].pos; Vector3 b1 = rotateAroundAxis(b0, root.nodes[node].pos, basis, 2.09f); Vector3 b2 = rotateAroundAxis(b0, root.nodes[node].pos, basis, 4.18f); //create vertices BasicVertex tmpVertex = new BasicVertex(); tmpVertex.pos = b0; vertices.Add(tmpVertex); tmpVertex = new BasicVertex(); tmpVertex.pos = b1; vertices.Add(tmpVertex); tmpVertex = new BasicVertex(); tmpVertex.pos = b2; vertices.Add(tmpVertex); //create texCoords BasicTexCoord tmpTexCoord = new BasicTexCoord(); float texV = (node % 2 == 0 ? 1.0f : 0.0f); tmpTexCoord.uv = new Vector2(0.0f, texV); texCoords.Add(tmpTexCoord); tmpTexCoord = new BasicTexCoord(); tmpTexCoord.uv = new Vector2(0.3f, texV); texCoords.Add(tmpTexCoord); tmpTexCoord = new BasicTexCoord(); tmpTexCoord.uv = new Vector2(0.6f, texV); texCoords.Add(tmpTexCoord); if (node == 0) { continue; } //create triangle BasicTriangle tmpTriangle = new BasicTriangle(); tmpTriangle.matid = 3; tmpTriangle.v0id = (uint)vertices.Count - 3; tmpTriangle.v1id = (uint)vertices.Count - 0; tmpTriangle.v2id = (uint)vertices.Count - 4; tmpTriangle.t0id = (uint)vertices.Count - 3; tmpTriangle.t1id = (uint)vertices.Count - 0; tmpTriangle.t2id = (uint)vertices.Count - 4; triangles.Add(tmpTriangle); tmpTriangle = new BasicTriangle(); tmpTriangle.matid = 3; tmpTriangle.v0id = (uint)vertices.Count - 4; tmpTriangle.v1id = (uint)vertices.Count - 0; tmpTriangle.v2id = (uint)vertices.Count - 1; tmpTriangle.t0id = (uint)vertices.Count - 4; tmpTriangle.t1id = (uint)vertices.Count - 0; tmpTriangle.t2id = (uint)vertices.Count - 1; triangles.Add(tmpTriangle); tmpTriangle = new BasicTriangle(); tmpTriangle.matid = 3; tmpTriangle.v0id = (uint)vertices.Count - 4; tmpTriangle.v1id = (uint)vertices.Count - 1; tmpTriangle.v2id = (uint)vertices.Count - 5; tmpTriangle.t0id = (uint)vertices.Count - 4; tmpTriangle.t1id = (uint)vertices.Count - 1; tmpTriangle.t2id = (uint)vertices.Count - 5; triangles.Add(tmpTriangle); tmpTriangle = new BasicTriangle(); tmpTriangle.matid = 3; tmpTriangle.v0id = (uint)vertices.Count - 5; tmpTriangle.v1id = (uint)vertices.Count - 1; tmpTriangle.v2id = (uint)vertices.Count - 2; tmpTriangle.t0id = (uint)vertices.Count - 5; tmpTriangle.t1id = (uint)vertices.Count - 1; tmpTriangle.t2id = (uint)vertices.Count - 2; triangles.Add(tmpTriangle); tmpTriangle = new BasicTriangle(); tmpTriangle.matid = 3; tmpTriangle.v0id = (uint)vertices.Count - 5; tmpTriangle.v1id = (uint)vertices.Count - 2; tmpTriangle.v2id = (uint)vertices.Count - 0; tmpTriangle.t0id = (uint)vertices.Count - 5; tmpTriangle.t1id = (uint)vertices.Count - 2; tmpTriangle.t2id = (uint)vertices.Count - 0; triangles.Add(tmpTriangle); tmpTriangle = new BasicTriangle(); tmpTriangle.matid = 3; tmpTriangle.v0id = (uint)vertices.Count - 5; tmpTriangle.v1id = (uint)vertices.Count - 0; tmpTriangle.v2id = (uint)vertices.Count - 3; tmpTriangle.t0id = (uint)vertices.Count - 5; tmpTriangle.t1id = (uint)vertices.Count - 0; tmpTriangle.t2id = (uint)vertices.Count - 3; triangles.Add(tmpTriangle); } } //initialize ivy mesh //loadTextures(); prepareData(); calculateVertexNormals(); prepareData(); //createDisplayList(true); }