/// <summary> /// 调整前后枝干的顶点 /// </summary> private void AdjustBranch() { if (m_PairedBranchIndexes.Count == 1 && m_PairedBranchIndexes[0].PreIndex == null) { AdjustFreshBranch(); return; } /* * 获取前后两个关键帧的枝干对象 * 用于后续获取顶点以及更改顶点 */ GameObject preBranch = m_PairedBranchIndexes[0].PreIndex.Belong; GameObject curBranch = m_PairedBranchIndexes[0].CurIndex.Belong; Vector3[] preVertices = GameObjectOperation.GetVertices(preBranch); Vector3[] vertices = new Vector3[GameObjectOperation.GetVertices(curBranch).Length]; //该顶点数组用于存放修改后的前关键帧顶点 /* * 遍历已经匹配好的Index * 根据PairedIndex中记录的前后Index的数据 * 对前后关键帧中枝干的数据进行修改 */ foreach (PairedIndex <BranchIndex> pairedBranchIndex in m_PairedBranchIndexes) { BranchIndex preBranchIndex = pairedBranchIndex.PreIndex; BranchIndex curBranchIndex = pairedBranchIndex.CurIndex; if (curBranchIndex.IsFirstBranch() && preBranchIndex.IsFirstBranch()) //均为第一个枝干 { CopyVertices(preVertices, preBranchIndex.BottomVerticesIndex, vertices, curBranchIndex.BottomVerticesIndex, 40); } else if (preBranchIndex != null) //若存在匹配的第一个关键帧的枝干索引,则将第一个关键帧枝干索引指向的顶点插入到第二个关键帧枝干索引指向的顶点位置中 { CopyVertices(preVertices, preBranchIndex.TopVerticesIndex, vertices, curBranchIndex.TopVerticesIndex); } else//若第二个关键帧枝干不存在匹配的第一个关键帧枝干索引,则遍历其前驱,直至有存在的第一个关键帧枝干索引,并将该枝干索引指向的顶点插入到第二个关键帧枝干索引指向的顶点位置中 { CopyVertices(vertices, curBranchIndex.Previous.TopVerticesIndex, vertices, curBranchIndex.TopVerticesIndex); } } //更新对象 GameObjectOperation.UpdateMeshInfo(preBranch, vertices, GameObjectOperation.GetUV(curBranch), GameObjectOperation.GetTriangleIndexes(curBranch)); AddPreObject(preBranch); AddCurObject(curBranch); }
/// <summary> /// 根据当前模型的数据写叶片长度和最大宽度 /// 后续则根据实际需要读取该文件,减少重复计算 /// </summary> private void WriteLeafLengthAndWidth() { if (m_MeshModelInstance == null) { throw new UnityException("Error Mesh Path"); } //实例化,否则无法获取顶点和UV坐标 GameObject meshModel = (GameObject)GameObject.Instantiate(m_MeshModelInstance); /* * 获取顶点坐标和UV坐标 * 用于后续计算长度和宽度 */ Vector3[] vertices = GameObjectOperation.GetVertices(meshModel.transform.GetChild(0).gameObject); Vector2[] uv = GameObjectOperation.GetUV(meshModel.transform.GetChild(0).gameObject); /* * 获取未放大和缩小的模型中 * 叶片的长度、宽度和叶片面积 * 用于后续与实际叶片长度和宽度或叶片面积做比较,确定模型的缩放比例 */ LeafLength = GetLeafLength(vertices, uv); //m LeafWidth = GetLeafWidth(vertices, uv); //m UniformLeafArea = ComputeLeafArea(meshModel); //㎡ /* * 清除GameObject * 防止模型显示 */ GameObject.Destroy(meshModel); /* * 记录叶片长度和宽度 * 用于写入文件中 */ string str = ""; str += "LeafLength " + LeafLength + " m\n"; str += "LeafWidth " + LeafWidth + " m\n"; str += "MeshArea " + UniformMeshArea + " m^2\n"; str += "LeafArea " + UniformLeafArea + " m^2\n"; str += "VisualPixelCount " + VisualPixelCount + "\n"; str += "PixelCount " + PixelCount + "\n"; str += "VisibilityRatio " + VisibilityRatio + "\n"; /* * 将数据写入文件 * 方便后续读取 */ //string filePath = System.Environment.CurrentDirectory + "\\Assets\\Resources\\" + m_strMeshPath.Remove(m_strMeshPath.LastIndexOf('.')) + ".tmp"; string directoryPath = System.Environment.CurrentDirectory + "\\Data"; if (!System.IO.Directory.Exists(directoryPath)) { Directory.CreateDirectory(directoryPath); } string filePath = directoryPath + "\\" + Path.GetFileNameWithoutExtension(m_strMeshPath) + ".data"; FileStream stream = new FileStream(filePath, FileMode.Create); StreamWriter writer = new StreamWriter(stream); writer.WriteLine(str); //写入 //完成写入,内存释放 writer.Close(); stream.Close(); }
private Vector3 RecordBranchModel(BranchIndex index, Vector3 bottom) { /* * 计算形态数据 * 根据形态数据即可绘制对应的GameObject */ index.MorphologicalSim(); if (cylinderObject.activeSelf) { cylinderObject.SetActive(false); } cylinderObject.transform.localRotation = Quaternion.Euler(Vector3.zero); cylinderObject.transform.position = bottom + new Vector3(0, index.Length / 2f, 0) * SCALE; //该节间的中心位置 cylinderObject.transform.localScale = new Vector3(index.Radius / DEFAULT_RADIUS, index.Length / DEFAULT_HEIGHT, index.Radius / DEFAULT_RADIUS) * SCALE; //尺寸 RotationGameObject(cylinderObject, bottom, index.Rotation); //旋转该圆柱体 Vector3[] vertices = GameObjectOperation.GetVerticesInWorld(cylinderObject); Vector2[] uv = GameObjectOperation.GetUV(cylinderObject); if (temp_Vertices.Count == 0) //最底端的节间 { for (int i = 0; i < 40; i++) { temp_Vertices.Add(vertices[i]); temp_UV.Add(uv[i]); } AddTriangles(0, 20); } else //非最底端节间 { for (int i = 0; i < 20; i++) { /* * 添加顶点 * 由于底端的顶点与前驱节间的顶点相同 * 故只用添加后20个顶点即可 */ temp_Vertices.Add(vertices[i + 20]); /* * 添加UV坐标 * 需要颠倒纹理(与上一个节间的纹理相反) * 确保连接处的纹理过渡不会突兀 */ temp_UV.Add(temp_UV[index.Previous.TopVerticesIndex - 20 + i]); } AddTriangles(index.Previous.TopVerticesIndex, temp_Vertices.Count - 20); } //删除GameObject,防止重复 //GameObject.Destroy(cylinderObject); /* * 补齐index的数据 * 用于后续生成节间 */ index.BottomVerticesIndex = index.Previous.TopVerticesIndex == -1 ? 0 : index.Previous.TopVerticesIndex; index.TopVerticesIndex = temp_Vertices.Count - 20; /* * 返回当前顶端的中心位置 * 由于枝干旋转,故根据顶端的顶点位置计算 */ return(GetCenterPoint(index.TopVerticesIndex, temp_Vertices)); }