public MeshMakerTriangle(int id, ref MeshMakerVertex vertex1, ref MeshMakerVertex vertex2, ref MeshMakerVertex vertex3) { ID = id; Vertex1 = vertex1; Vertex2 = vertex2; Vertex3 = vertex3; RefreshEdge(); }
/// <summary> /// 为所有面执行移除操作,条件是该面包含顶点vertex /// </summary> public static void RemoveByVertex(this List <MeshMakerTriangle> triangles, MeshMakerVertex vertex) { for (int i = 0; i < triangles.Count; i++) { if (triangles[i].Vertex1 == vertex || triangles[i].Vertex2 == vertex || triangles[i].Vertex3 == vertex) { triangles.RemoveAt(i); i--; } } }
/// <summary> /// 判断vertex1和vertex2是否相连,也就是判断是否存在于同一面中 /// </summary> public static bool IsConnected(this List <MeshMakerTriangle> triangles, MeshMakerVertex vertex1, MeshMakerVertex vertex2) { for (int i = 0; i < triangles.Count; i++) { if ((triangles[i].Vertex1 == vertex1 || triangles[i].Vertex2 == vertex1 || triangles[i].Vertex3 == vertex1) && (triangles[i].Vertex1 == vertex2 || triangles[i].Vertex2 == vertex2 || triangles[i].Vertex3 == vertex2)) { return(true); } } return(false); }
/// <summary> /// 清空鼠标当前选中的目标 /// </summary> private void ClearCheckedTarget() { if (_currentCheckedTriangle != null) { _currentCheckedTriangle = null; } if (_currentCheckedEdge != null) { _currentCheckedEdge = null; } if (_currentCheckedVertex != null) { _currentCheckedVertex = null; } }
/// <summary> /// 截获鼠标当前选中的目标 /// </summary> private void CaptureCheckedTarget() { if (!_secondaryHandle && Event.current.button == 1 && Event.current.isMouse && Event.current.type == EventType.MouseDown) { RaycastHit hit; if (Physics.Raycast(HandleUtility.GUIPointToWorldRay(Event.current.mousePosition), out hit)) { if (hit.triangleIndex >= 0 && hit.triangleIndex < _meshMaker.Triangles.Count) { _currentCheckedTriangle = _meshMaker.Triangles[hit.triangleIndex]; } else { ClearCheckedTarget(); } } else { ClearCheckedTarget(); } if (_currentCheckedTriangle != null) { switch (_currentEditMode) { case EditMode.Vertex: _currentCheckedVertex = _currentCheckedTriangle.GetVertexByClick(hit.point); break; case EditMode.Edge: _currentCheckedEdge = _currentCheckedTriangle.GetEdgeByClick(hit.point); SetEditEdge(); break; case EditMode.Face: SetEditTriangle(); break; } } } Selection.activeObject = _meshMaker.gameObject; ShowCheckedTarget(); }
/// <summary> /// 为所有面执行替换操作,将旧的顶点oldVertex替换为新的顶点newVertex /// </summary> public static void ReplaceVertex(this List <MeshMakerTriangle> triangles, MeshMakerVertex oldVertex, MeshMakerVertex newVertex) { for (int i = 0; i < triangles.Count; i++) { if (triangles[i].Vertex1 == oldVertex) { triangles[i].Vertex1 = newVertex; triangles[i].RefreshEdge(); } else if (triangles[i].Vertex2 == oldVertex) { triangles[i].Vertex2 = newVertex; triangles[i].RefreshEdge(); } else if (triangles[i].Vertex3 == oldVertex) { triangles[i].Vertex3 = newVertex; triangles[i].RefreshEdge(); } } }
/// <summary> /// 为所有面执行分割操作,条件是该面包含顶点vertex1和vertex2,并以新的顶点newVertex作为分割之后的顶点 /// </summary> public static void SegmentationTriangle(this List <MeshMakerTriangle> triangles, MeshMakerVertex vertex1, MeshMakerVertex vertex2, MeshMakerVertex newVertex) { List <MeshMakerTriangle> newTriangles = new List <MeshMakerTriangle>(); for (int i = 0; i < triangles.Count; i++) { if ((triangles[i].Vertex1 == vertex1 || triangles[i].Vertex1 == vertex2) && (triangles[i].Vertex2 == vertex1 || triangles[i].Vertex2 == vertex2)) { MeshMakerTriangle mmt1 = new MeshMakerTriangle(0, ref triangles[i].Vertex1, ref newVertex, ref triangles[i].Vertex3); MeshMakerTriangle mmt2 = new MeshMakerTriangle(0, ref newVertex, ref triangles[i].Vertex2, ref triangles[i].Vertex3); triangles.RemoveAt(i); newTriangles.Add(mmt1); newTriangles.Add(mmt2); i--; } else if ((triangles[i].Vertex2 == vertex1 || triangles[i].Vertex2 == vertex2) && (triangles[i].Vertex3 == vertex1 || triangles[i].Vertex3 == vertex2)) { MeshMakerTriangle mmt1 = new MeshMakerTriangle(0, ref triangles[i].Vertex1, ref triangles[i].Vertex2, ref newVertex); MeshMakerTriangle mmt2 = new MeshMakerTriangle(0, ref triangles[i].Vertex1, ref newVertex, ref triangles[i].Vertex3); triangles.RemoveAt(i); newTriangles.Add(mmt1); newTriangles.Add(mmt2); i--; } else if ((triangles[i].Vertex1 == vertex1 || triangles[i].Vertex1 == vertex2) && (triangles[i].Vertex3 == vertex1 || triangles[i].Vertex3 == vertex2)) { MeshMakerTriangle mmt1 = new MeshMakerTriangle(0, ref triangles[i].Vertex1, ref triangles[i].Vertex2, ref newVertex); MeshMakerTriangle mmt2 = new MeshMakerTriangle(0, ref newVertex, ref triangles[i].Vertex2, ref triangles[i].Vertex3); triangles.RemoveAt(i); newTriangles.Add(mmt1); newTriangles.Add(mmt2); i--; } } triangles.AddRange(newTriangles); }
/// <summary> /// 初始化 /// </summary> private void Init() { #region 检测Mesh this.CompileNoEditor(delegate() { DestroyImmediate(this); return; }); if (EditorApplication.isPlaying) { DestroyImmediate(this); return; } string msseage = "OK"; if (GetComponent <MeshFilter>() == null) { msseage = "游戏物体缺少组件 MeshFilter!"; } else if (GetComponent <MeshRenderer>() == null) { msseage = "游戏物体缺少组件 MeshRenderer!"; } else if (GetComponent <MeshFilter>().sharedMesh.vertexCount > _astrictVertexNum) { msseage = "游戏物体顶点太多,我无法处理!"; } if (msseage != "OK") { DestroyImmediate(this); Debug.LogWarning(msseage); return; } #endregion #region 识别MeshVertex _allUVs = new List <Vector2>(GetComponent <MeshFilter>().sharedMesh.uv); _allNormals = new List <Vector3>(GetComponent <MeshFilter>().sharedMesh.normals); _allVertexs = new List <Vector3>(GetComponent <MeshFilter>().sharedMesh.vertices); Vertexs = new List <MeshMakerVertex>(); List <int> repetitionVertices = new List <int>(); for (int i = 0; i < _allVertexs.Count; i++) { this.CompileOnlyEditor(delegate() { EditorUtility.DisplayProgressBar("识别顶点", "正在识别顶点(" + i + "/" + _allVertexs.Count + ")......", 1.0f / _allVertexs.Count * i); }); if (repetitionVertices.Contains(i)) { continue; } List <int> verticesGroup = new List <int>(); verticesGroup.Add(i); for (int j = i + 1; j < _allVertexs.Count; j++) { if (_allVertexs[i] == _allVertexs[j]) { verticesGroup.Add(j); repetitionVertices.Add(j); } } Vertexs.Add(new MeshMakerVertex(Vertexs.Count, transform.localToWorldMatrix.MultiplyPoint3x4(_allVertexs[i]), _allUVs[i], _allNormals[i], verticesGroup)); } #endregion #region 识别MeshTriangle _allTriangles = new List <int>(GetComponent <MeshFilter>().sharedMesh.triangles); Triangles = new List <MeshMakerTriangle>(); for (int i = 0; (i + 2) < _allTriangles.Count; i += 3) { this.CompileOnlyEditor(delegate() { EditorUtility.DisplayProgressBar("识别顶点", "正在识别顶点(" + i + "/" + _allTriangles.Count + ")......", 1.0f / _allTriangles.Count * i); }); MeshMakerVertex mmv1 = Vertexs.GetVertexByIndex(_allTriangles[i]); MeshMakerVertex mmv2 = Vertexs.GetVertexByIndex(_allTriangles[i + 1]); MeshMakerVertex mmv3 = Vertexs.GetVertexByIndex(_allTriangles[i + 2]); MeshMakerTriangle mmt = new MeshMakerTriangle(Triangles.Count, ref mmv1, ref mmv2, ref mmv3); Triangles.Add(mmt); } for (int i = 0; i < Vertexs.Count; i++) { Vertexs[i].VertexIndexs.Clear(); } #endregion #region 重构Mesh if (Target) { DestroyImmediate(Target); } Target = new GameObject(transform.name + "(Clone)"); Target.transform.SetParent(transform); Target.transform.localPosition = Vector3.zero; Target.transform.localRotation = Quaternion.Euler(Vector3.zero); Target.transform.localScale = Vector3.one; Target.hideFlags = HideFlags.HideInHierarchy; _meshFilter = Target.AddComponent <MeshFilter>(); _meshRenderer = Target.AddComponent <MeshRenderer>(); _meshRenderer.sharedMaterial = GetComponent <MeshRenderer>().sharedMaterial; _meshCollider = Target.AddComponent <MeshCollider>(); GenerateMesh(); GetComponent <MeshRenderer>().enabled = false; if (GetComponent <Collider>()) { GetComponent <Collider>().enabled = false; } EditorUtility.ClearProgressBar(); #endregion #region 其他编辑器参数初始化 CheckedColor = Color.red; HoverColor = Color.green; VertexHandleSize = 0.005f; IsCanEdit = true; #endregion }
/// <summary> /// 高级编辑模式 /// </summary> private void SecondaryHandle() { if (_secondaryHandle) { #region 顶点模式 if (_currentEditMode == EditMode.Vertex && _currentCheckedVertex != null) { switch (_secondaryHandleMode) { case SecondaryHandleMode.Delete: _meshMaker.Vertexs.Remove(_currentCheckedVertex); _meshMaker.Vertexs.RefreshID(); _meshMaker.Triangles.RemoveByVertex(_currentCheckedVertex); _meshMaker.Triangles.RefreshID(); _meshMaker.GenerateMesh(); _currentCheckedVertex = null; StopSecondaryHandle(); break; case SecondaryHandleMode.Welding: Vector3 wv = _meshMaker.ScreenToWorldPointInScene(_sceneCamera, Event.current.mousePosition, _currentCheckedVertex.Vertex); Handles.DrawDottedLine(_currentCheckedVertex.Vertex, wv, 0.2f); Handles.Label(wv, " 请选择焊接目标"); if (Event.current.button == 1 && Event.current.isMouse && Event.current.type == EventType.MouseDown) { RaycastHit hit; if (Physics.Raycast(HandleUtility.GUIPointToWorldRay(Event.current.mousePosition), out hit)) { if (hit.triangleIndex >= 0 && hit.triangleIndex < _meshMaker.Triangles.Count) { MeshMakerVertex mmv = _meshMaker.Triangles[hit.triangleIndex].GetVertexByClick(hit.point); if (mmv != _currentCheckedVertex) { _meshMaker.Vertexs.Remove(_currentCheckedVertex); _meshMaker.Vertexs.RefreshID(); _meshMaker.Triangles.RemoveByVertexs(_currentCheckedVertex, mmv); _meshMaker.Triangles.ReplaceVertex(_currentCheckedVertex, mmv); _meshMaker.Triangles.RefreshID(); _meshMaker.GenerateMesh(); _currentCheckedVertex = null; } } } StopSecondaryHandle(); } break; case SecondaryHandleMode.Clone: Vector3 cv = _meshMaker.ScreenToWorldPointInScene(_sceneCamera, Event.current.mousePosition, _currentCheckedVertex.Vertex); Handles.DrawDottedLine(_currentCheckedVertex.Vertex, cv, 0.2f); Handles.Label(cv, " 请选择参照目标"); if (Event.current.button == 1 && Event.current.isMouse && Event.current.type == EventType.MouseDown) { RaycastHit hit; if (Physics.Raycast(HandleUtility.GUIPointToWorldRay(Event.current.mousePosition), out hit)) { if (hit.triangleIndex >= 0 && hit.triangleIndex < _meshMaker.Triangles.Count) { MeshMakerVertex mmv = _meshMaker.Triangles[hit.triangleIndex].GetVertexByClick(hit.point); if (mmv != _currentCheckedVertex && _meshMaker.Triangles.IsConnected(_currentCheckedVertex, mmv)) { Vector3 vertex = Vector3.Lerp(_currentCheckedVertex.Vertex, mmv.Vertex, 0.5f); Vector2 uv = Vector2.Lerp(_currentCheckedVertex.UV, mmv.UV, 0.5f); MeshMakerVertex newMmv = new MeshMakerVertex(0, vertex, uv, _currentCheckedVertex.Normal, new List <int>()); _meshMaker.Vertexs.Add(newMmv); _meshMaker.Vertexs.RefreshID(); _meshMaker.Triangles.SegmentationTriangle(mmv, _currentCheckedVertex, newMmv); _meshMaker.Triangles.RefreshID(); _meshMaker.GenerateMesh(); _currentCheckedVertex = null; } } } StopSecondaryHandle(); } break; } } #endregion } }
private void Init() { _meshMaker = target as MeshMaker; if (_meshMaker == null || EditorApplication.isPlaying) { return; } TransformChange(_meshMaker); _currentHoverTriangle = null; _currentCheckedTriangle = null; _currentCheckedVertex = null; _currentCheckedEdge = null; _currentHandleTool = HandleTool.None; _currentEditMode = EditMode.Vertex; _currentEditTriangle = new GameObject("Triangle"); _currentEditTriangle.transform.SetParent(_meshMaker.Target.transform); _currentEditTriangle.hideFlags = HideFlags.HideInHierarchy; _currentEditTriangleVertex1 = new GameObject("Vertex1"); _currentEditTriangleVertex1.transform.SetParent(_currentEditTriangle.transform); _currentEditTriangleVertex1.hideFlags = HideFlags.HideInHierarchy; _currentEditTriangleVertex2 = new GameObject("Vertex2"); _currentEditTriangleVertex2.transform.SetParent(_currentEditTriangle.transform); _currentEditTriangleVertex2.hideFlags = HideFlags.HideInHierarchy; _currentEditTriangleVertex3 = new GameObject("Vertex3"); _currentEditTriangleVertex3.transform.SetParent(_currentEditTriangle.transform); _currentEditTriangleVertex3.hideFlags = HideFlags.HideInHierarchy; _currentEditEdge = new GameObject("Edge"); _currentEditEdge.transform.SetParent(_meshMaker.Target.transform); _currentEditEdge.hideFlags = HideFlags.HideInHierarchy; _currentEditEdgeVertex1 = new GameObject("Vertex1"); _currentEditEdgeVertex1.transform.SetParent(_currentEditEdge.transform); _currentEditEdgeVertex1.hideFlags = HideFlags.HideInHierarchy; _currentEditEdgeVertex2 = new GameObject("Vertex2"); _currentEditEdgeVertex2.transform.SetParent(_currentEditEdge.transform); _currentEditEdgeVertex2.hideFlags = HideFlags.HideInHierarchy; if (_vertexButtonContent == null) { Texture2D t2d = AssetDatabase.LoadAssetAtPath("Assets/MeshEditor/MeshMaker/Editor/Texture/Vertex.png", typeof(Texture2D)) as Texture2D; _vertexButtonContent = new GUIContent("", t2d, "Vertex Edit Mode"); } if (_edgeButtonContent == null) { Texture2D t2d = AssetDatabase.LoadAssetAtPath("Assets/MeshEditor/MeshMaker/Editor/Texture/Edge.png", typeof(Texture2D)) as Texture2D; _edgeButtonContent = new GUIContent("", t2d, "Edge Edit Mode"); } if (_faceButtonContent == null) { Texture2D t2d = AssetDatabase.LoadAssetAtPath("Assets/MeshEditor/MeshMaker/Editor/Texture/Face.png", typeof(Texture2D)) as Texture2D; _faceButtonContent = new GUIContent("", t2d, "Face Edit Mode"); } if (_noneButtonContent == null) { Texture2D t2d = AssetDatabase.LoadAssetAtPath("Assets/MeshEditor/MeshMaker/Editor/Texture/None.png", typeof(Texture2D)) as Texture2D; _noneButtonContent = new GUIContent("", t2d, "None Edit Mode"); } _secondaryHandle = false; _secondaryHandleMode = SecondaryHandleMode.None; _sceneCamera = SceneView.lastActiveSceneView.camera; Undo.undoRedoPerformed += OnRecord; }
public MeshMakerEdge(ref MeshMakerVertex vertex1, ref MeshMakerVertex vertex2) { Vertex1 = vertex1; Vertex2 = vertex2; }