public bool IsLinkedEdge(apMeshEdge edge) { bool isORCond = (_vert1 == edge._vert1 || _vert1 == edge._vert2) || (_vert2 == edge._vert1 || _vert2 == edge._vert2); return(isORCond && !IsSameEdge(edge)); // }
public void UpdateSnapEdgeGUIOnly(Vector2 mousePos, bool isShift, bool isCtrl, bool isPressed) { if (Vector2.SqrMagnitude(_isTmpEdgeWire_SnapCheck_MousePos - mousePos) > 1.0f || _isTmpEdgeWire_SnapCheck_PrevShift != isShift || _isTmpEdgeWire_SnapCheck_PrevCtrl != isCtrl) { _isTmpEdgeWire_SnapToEdge = false; _tmpEdgeWire_SnapToEdge = Vector2.zero; //if (isShift && _mesh != null && !isCtrl && _curVertex == null) if (isShift && _mesh != null && !isCtrl && !isPressed) { //추가 //가장 가까운 Edge의 점을 찾는다. apMeshEdge nearestEdge = GetMeshNearestEdge(mousePos, _mesh, 3.0f); //<<기본적인 5가 아닌 3이다. 제한적임 if (nearestEdge != null) { _isTmpEdgeWire_SnapToEdge = true; _tmpEdgeWire_SnapToEdge = nearestEdge.GetNearestPosOnEdge(apGL.GL2World(mousePos) + _mesh._offsetPos); } } //Debug.Log("UpdateSnapEdgeGUIOnly >> " + _isTmpEdgeWire_SnapToEdge); _isTmpEdgeWire_SnapCheck_MousePos = mousePos; _isTmpEdgeWire_SnapCheck_PrevShift = isShift; _isTmpEdgeWire_SnapCheck_PrevCtrl = isCtrl; } //_tmpEdgeWire_MousePos = mousePos; }
private apMeshEdge GetMeshNearestEdge(Vector2 posGL, apMesh mesh, float offsetGL) { apMeshEdge curEdge = null; //Vector2 posW = apGL.GL2World(posGL) + mesh._offsetPos; Vector2 vPos1GL = Vector2.zero; Vector2 vPos2GL = Vector2.zero; float minX = 0.0f; float maxX = 0.0f; float minY = 0.0f; float maxY = 0.0f; float curDist = 0.0f; float minDist = 0.0f; apMeshEdge minEdge = null; for (int i = 0; i < mesh._edges.Count; i++) { curEdge = mesh._edges[i]; if (curEdge._vert1 == null || curEdge._vert2 == null) { continue; } //기본 사각 범위안에 있는지 확인 vPos1GL = apGL.World2GL(curEdge._vert1._pos - mesh._offsetPos); vPos2GL = apGL.World2GL(curEdge._vert2._pos - mesh._offsetPos); minX = Mathf.Min(vPos1GL.x, vPos2GL.x); maxX = Mathf.Max(vPos1GL.x, vPos2GL.x); minY = Mathf.Min(vPos1GL.y, vPos2GL.y); maxY = Mathf.Max(vPos1GL.y, vPos2GL.y); if (posGL.x < minX || maxX < posGL.x || posGL.y < minY || maxY < posGL.y) { continue; } curDist = apEditorUtil.DistanceFromLine( vPos1GL, vPos2GL, posGL); if (curDist < offsetGL) { if (minEdge == null || curDist < minDist) { minDist = curDist; minEdge = curEdge; } } } return(minEdge); }
public static CloneVertex MakeCrossPoint(Vector2 pos, apMeshEdge splitEdge) { CloneVertex newCVert = new CloneVertex(); newCVert._pos = pos; newCVert._isCrossOnAxis = true; newCVert._srcSplitEdge = splitEdge; newCVert._compareToMirror = 0; return(newCVert); }
public void DrawMeshEdgeOnly(apMesh mesh, apMatrix3x3 matrix) { try { //0. 메시, 텍스쳐가 없을 때 //if (mesh == null || mesh._textureData == null || mesh._textureData._image == null)//이전 코드 if (mesh == null || mesh.LinkedTextureData == null || mesh.LinkedTextureData._image == null) //변경 코드 { return; } //1. 모든 메시를 보여줄때 (또는 클리핑된 메시가 없을 때) => Color meshEdgeColor = new Color(1.0f, 0.5f, 0.0f, 0.9f); Color meshHiddenEdgeColor = new Color(1.0f, 1.0f, 0.0f, 0.7f); matrix *= mesh.Matrix_VertToLocal; Vector2 pos0 = Vector2.zero, pos1 = Vector2.zero; if (mesh._edges.Count > 0) { _matBatch.SetPass_Color(); _matBatch.SetClippingSize(_glScreenClippingSize); GL.Begin(GL.LINES); for (int i = 0; i < mesh._edges.Count; i++) { pos0 = matrix.MultiplyPoint(mesh._edges[i]._vert1._pos); pos1 = matrix.MultiplyPoint(mesh._edges[i]._vert2._pos); DrawLine(pos0, pos1, meshEdgeColor, false); } for (int iPoly = 0; iPoly < mesh._polygons.Count; iPoly++) { for (int iHE = 0; iHE < mesh._polygons[iPoly]._hidddenEdges.Count; iHE++) { apMeshEdge hiddenEdge = mesh._polygons[iPoly]._hidddenEdges[iHE]; pos0 = matrix.MultiplyPoint(hiddenEdge._vert1._pos); pos1 = matrix.MultiplyPoint(hiddenEdge._vert2._pos); DrawLine(pos0, pos1, meshHiddenEdgeColor, false); } } GL.End(); } } catch (Exception ex) { Debug.LogException(ex); } }
public static apVertex GetSharedVertex(apMeshEdge edge1, apMeshEdge edge2) { if (edge1._vert1 == edge2._vert1 || edge1._vert1 == edge2._vert2) { return(edge1._vert1); } else if (edge1._vert2 == edge2._vert1 || edge1._vert2 == edge2._vert2) { return(edge1._vert2); } return(null); }
public static apVertex[] Get3VerticesOf2Edges(apMeshEdge edge1, apMeshEdge edge2) { apVertex[] verts = new apVertex[3]; verts[0] = edge1._vert1; verts[1] = edge1._vert2; if (edge2._vert1 == edge1._vert1 || edge2._vert1 == edge1._vert2) { verts[2] = edge2._vert2; } else { verts[2] = edge2._vert1; } return(verts); }
public static apVertex[] GetNoSharedVertex(apMeshEdge edge1, apMeshEdge edge2) { if (edge1._vert1 == edge2._vert1) { return(new apVertex[] { edge1._vert2, edge2._vert2 }); } if (edge1._vert1 == edge2._vert2) { return(new apVertex[] { edge1._vert2, edge2._vert1 }); } if (edge1._vert2 == edge2._vert1) { return(new apVertex[] { edge1._vert1, edge2._vert2 }); } if (edge1._vert2 == edge2._vert2) { return(new apVertex[] { edge1._vert1, edge2._vert1 }); } return(null); }
public void RemoveMirrorEdge(apMeshEdge removedEdge, apMesh mesh) { ClearMovedVertex(); //두개의 Vertex => Mirror 위치 각자 계산 => mesh에서 검색 if (removedEdge == null) { return; } apVertex srcVert1 = removedEdge._vert1; apVertex srcVert2 = removedEdge._vert2; if (srcVert1 == null || srcVert2 == null) { return; } Vector2 mirrorPos1 = GetMirrorPosByMesh(srcVert1._pos, mesh); Vector2 mirrorPos2 = GetMirrorPosByMesh(srcVert2._pos, mesh); apVertex mirrorVert1 = FindNearestVertex(mirrorPos1, mesh, 2.0f, srcVert1); apVertex mirrorVert2 = FindNearestVertex(mirrorPos2, mesh, 2.0f, srcVert2); if (mirrorVert1 == null || mirrorVert2 == null || mirrorVert1 == mirrorVert2 || (mirrorVert1 == srcVert1 && mirrorVert2 == srcVert2) || (mirrorVert1 == srcVert2 && mirrorVert2 == srcVert1) ) { return; } //이제 대상이 되는 Edge를 찾자 apMeshEdge mirrorEdge = mesh._edges.Find(delegate(apMeshEdge a) { return(a.IsSameEdge(mirrorVert1, mirrorVert2)); }); if (mirrorEdge != null) { mesh.RemoveEdge(mirrorEdge); } }
public bool IsSameEdge(apMeshEdge edge) { return(IsSameEdge(edge._vert1, edge._vert2)); }
private void MakeTriangles() { _tris.Clear(); List <apMeshEdge> allEdges = new List <apMeshEdge>(); for (int i = 0; i < _edges.Count; i++) { allEdges.Add(_edges[i]); } for (int i = 0; i < _hidddenEdges.Count; i++) { allEdges.Add(_hidddenEdges[i]); } for (int iEdge = 0; iEdge < allEdges.Count; iEdge++) { apMeshEdge baseEdge = allEdges[iEdge]; if (!baseEdge._isHidden) { //Hidden이 아닌 경우 //한개의 Edge는 한개의 Tri에만 들어간다. bool isExistTri = _tris.Exists(delegate(apMeshTri a) { return(a.IsIncludeEdge(baseEdge)); }); if (isExistTri) { //이미 Tri 계산에 사용된 Edge이다. continue; } } //이제 여기에 연결된 Edge 하나를 찾는다. (두번째 Edge) //처음엔 "기본 Edge", 여기서 못찾으면 "Hidden Edge"에서 찾자 //한개의 Edge에 대해서 최대 2개의 Tri만 나온다. //2개를 만들면 더이상 처리하지 말자 int nCreatedTri = 0; for (int iNext = 0; iNext < allEdges.Count; iNext++) { apMeshEdge nextEdge = allEdges[iNext]; if (baseEdge == nextEdge) { //같은거다 continue; } if (!nextEdge.IsLinkedEdge(baseEdge)) { //연결되지 않았다. continue; } //이 둘을 연결할 선분은 있는지 체크 //공유하고 있지 않은 버텍스 두개를 구하자 apVertex[] noSharedVerts = apMeshEdge.GetNoSharedVertex(baseEdge, nextEdge); if (noSharedVerts == null) { continue; } //해당 Edge를 포함하는 Edge가 있는가 apMeshEdge thirdEdge = allEdges.Find(delegate(apMeshEdge a) { return(a.IsSameEdge(noSharedVerts[0], noSharedVerts[1])); }); if (thirdEdge == null) { continue; } apVertex[] allVerts = apMeshEdge.Get3VerticesOf2Edges(baseEdge, nextEdge); //base, next, third 완성 bool isExistTri = _tris.Exists(delegate(apMeshTri a) { return(a.IsSameTri(allVerts[0], allVerts[1], allVerts[2])); }); if (!isExistTri) { //겹치는 Tri가 없다. //만들자 apMeshTri newTri = new apMeshTri(); newTri.SetVertices(allVerts[0], allVerts[1], allVerts[2]); _tris.Add(newTri); nCreatedTri++; } if (nCreatedTri >= 2) { //처리 끝 break; } } //if (_tris.Count >= nNeedTri) //{ // //이미 이 폴리곤에서 만들 수 있는 최대의 Tri를 만들었다. // break; //} } //마지막에 Sort SortTriByDepth(); }
//---------------------------------------------------------------- public void AddMirrorVertex(apVertex prevVert, apVertex addedVert, apMesh mesh, bool isAddEdge, bool isShift, bool isNewVert, bool isAddVertexWithSplit) { apVertex mirrorVert_Prev = null; apVertex mirrorVert_Next = null; //float mirrorOffset = _editor._meshTRSOption_MirrorOffset; //float clickableOffset = Mathf.Max(6.0f, mirrorOffset);//6은 기본 클릭 범위 float clickableOffset = 6.0f; if (isNewVert) { //새로운 버텍스를 생성했다면 미러쪽도 새로 만드는 방향으로 해야한다. clickableOffset = 2.0f; } bool isSnap = _editor._meshTRSOption_MirrorSnapVertOnRuler; //추가된 버텍스가 있다 (각각 Prev, Next에 대해서 동일한 처리) //=> 1) 축에 있다면 // => Snap 옵션이 켜졌다면 Mirror대신 축으로 위치를 보정한다. (미러 생성 안하고 mirrorVert를 이걸로 설정) // => Snap 옵션이 꺼졌다면 처리하지 않는다. (Mirror가 안됨) //=> 2) 미러 위치를 계산한다. // => 근처에 버텍스가 있다면 그걸 선택하고, 위치를 보정한다. (Prev와 Next는 같은 점을 공유할 수 없다.) // => 근처에 버텍스가 없다면 새로 생성한다. //=> isAddEdge가 True일 때, mirrorVert Prev, Next가 모두 있다면 Edge 생성. 단, 서로 교차된 경우는 생략한다. if (prevVert != null) { if (IsOnAxisByMesh(prevVert._pos, mesh)) { //1) 축에 있는가 if (isSnap) { //=> 위치만 보정한다. mirrorVert_Prev = prevVert; mirrorVert_Prev._pos = GetAxisPosToSnap(prevVert._pos, mesh); } else { //=> 위치 보정 없이 그냥 선택한다. mirrorVert_Prev = prevVert; } } else { //2) 축 바깥이라면 미러 위치를 계산한다. Vector2 mirrorPos = GetMirrorPosByMesh(prevVert._pos, mesh); //근처에 Vertex가 있는가 apVertex nearestVert = FindNearestVertex(mirrorPos, mesh, clickableOffset); if (nearestVert != null) { //=> 이걸 선택하고 위치만 보정한다. mirrorVert_Prev = nearestVert; mirrorVert_Prev._pos = mirrorPos; } else { //=> 새로 생성하자 mirrorVert_Prev = mesh.AddVertexAutoUV(mirrorPos); } } } if (addedVert != null && prevVert != addedVert) { if (IsOnAxisByMesh(addedVert._pos, mesh)) { //1) 축에 있는가 if (isSnap) { //=> 위치만 보정한다. mirrorVert_Next = addedVert; mirrorVert_Next._pos = GetAxisPosToSnap(addedVert._pos, mesh); } else { //=> 위치 보정 없이 그냥 선택한다. mirrorVert_Next = addedVert; } } else { //2) 축 바깥이라면 미러 위치를 계산한다. Vector2 mirrorPos = GetMirrorPosByMesh(addedVert._pos, mesh); //근처에 Vertex가 있는가 + Prev와 다른 Vertex인가 apVertex nearestVert = FindNearestVertex(mirrorPos, mesh, clickableOffset); if (nearestVert != null && mirrorVert_Prev != nearestVert) { //=> 이걸 선택하고 위치만 보정한다. mirrorVert_Next = nearestVert; mirrorVert_Next._pos = mirrorPos; } else { //=> 새로 생성하자 if (isAddVertexWithSplit) { //만약 원 소스가 Edge를 Split하고 Vertex를 만든 거라면, //Mirror도 주변의 Edge를 Split해야한다. apMeshEdge nearestEdge = GetMeshNearestEdge(mirrorPos, mesh, 3.0f); if (nearestEdge != null) { Vector2 splitPos = nearestEdge.GetNearestPosOnEdge(mirrorPos); if (Mathf.Abs(splitPos.x - nearestEdge._vert1._pos.x) < 1 && Mathf.Abs(splitPos.y - nearestEdge._vert1._pos.y) < 1) { //Vert1과 겹친다. mirrorVert_Next = nearestEdge._vert1; } else if (Mathf.Abs(splitPos.x - nearestEdge._vert2._pos.x) < 1 && Mathf.Abs(splitPos.y - nearestEdge._vert2._pos.y) < 1) { //Vert2와 겹친다. mirrorVert_Next = nearestEdge._vert2; } else { //겹치는게 없다. mirrorVert_Next = mesh.SplitEdge(nearestEdge, splitPos); } } } else { mirrorVert_Next = mesh.AddVertexAutoUV(mirrorPos); } } } } //if(!isAddEdge) //{ // Debug.LogError("Add Edge => False"); //} if (isAddEdge && mirrorVert_Prev != null && mirrorVert_Next != null) { //Edge를 추가하자 //단, 두개가 서로 Mirror된게 아니라면 생략 if ((mirrorVert_Prev == prevVert && mirrorVert_Next == addedVert) || (mirrorVert_Next == prevVert && mirrorVert_Prev == addedVert)) //<<또는 그 반대 { //새로 만드는거 실패. //서로 교차되고 있었다. //Shift 키를 누른 상태라면 => Mirror 위치에 중점을 만들자. if (isShift && mirrorVert_Prev != mirrorVert_Next) { //Mirror의 양쪽에 위치한 경우 bool isCounterSize = false; Vector2 centerPos = (mirrorVert_Prev._pos + mirrorVert_Next._pos) * 0.5f; if (mesh._isMirrorX) { if ((mirrorVert_Prev._pos.x - mesh._mirrorAxis.x) * (mirrorVert_Next._pos.x - mesh._mirrorAxis.x) < 0.0f) { //축으로부터 X 변화량의 곱이 -1인 경우 isCounterSize = true; centerPos.x = mesh._mirrorAxis.x; } } else { if ((mirrorVert_Prev._pos.y - mesh._mirrorAxis.y) * (mirrorVert_Next._pos.y - mesh._mirrorAxis.y) < 0.0f) { //축으로부터 Y 변화량의 곱이 -1인 경우 isCounterSize = true; centerPos.y = mesh._mirrorAxis.y; } } if (isCounterSize) { apMeshEdge existEdge = mesh._edges.Find(delegate(apMeshEdge a) { return(a.IsSameEdge(mirrorVert_Prev, mirrorVert_Next)); }); if (existEdge != null) { //분할하자 mesh.SplitEdge(existEdge, centerPos); //apVertex centerVert = mesh.AddVertexAutoUV(centerPos); //mesh.RemoveEdge(existEdge); //if (centerVert != null) //{ // mesh.MakeNewEdge(mirrorVert_Prev, centerVert, false); // mesh.MakeNewEdge(mirrorVert_Next, centerVert, false); //} //Debug.Log("Split Edge"); } } } } else { //새로운 Mirror Vertex를 만들자. mesh.MakeNewEdge(mirrorVert_Prev, mirrorVert_Next, isShift); //Debug.Log("Add Mirror Edge : " + isShift); } } if (mirrorVert_Prev != null) { mesh.RefreshVertexAutoUV(mirrorVert_Prev); } if (mirrorVert_Next != null) { mesh.RefreshVertexAutoUV(mirrorVert_Next); } ClearMovedVertex(); }
public bool IsIncludeEdge(apMeshEdge edge) { return((edge._vert1 == _verts[0] || edge._vert1 == _verts[1] || edge._vert1 == _verts[2]) && (edge._vert2 == _verts[0] || edge._vert2 == _verts[1] || edge._vert2 == _verts[2])); }
public void DrawMesh(apMesh mesh, apMatrix3x3 matrix, Color color2X, bool isShowAllTexture, bool isDrawOutline, bool isDrawEdge, bool isDrawToneOutline = false) { try { //0. 메시, 텍스쳐가 없을 때 //if (mesh == null || mesh._textureData == null || mesh._textureData._image == null)//이전 코드 if (mesh == null || mesh.LinkedTextureData == null || mesh.LinkedTextureData._image == null) //변경 코드 { return; } //1. 모든 메시를 보여줄때 (또는 클리핑된 메시가 없을 때) => Color textureColor = new Color(0.5f, 0.5f, 0.5f, 1.0f); //Color shadedTextureColor = new Color(0.3f, 0.3f, 0.3f, 1.0f); Color atlasBorderColor = new Color(0.0f, 1.0f, 1.0f, 0.5f); Color meshEdgeColor = new Color(1.0f, 0.5f, 0.0f, 0.9f); Color meshHiddenEdgeColor = new Color(1.0f, 1.0f, 0.0f, 0.7f); matrix *= mesh.Matrix_VertToLocal; if (isShowAllTexture) { //DrawTexture(mesh._textureData._image, matrix, mesh._textureData._width, mesh._textureData._height, textureColor, -10); DrawTexture(mesh.LinkedTextureData._image, matrix, mesh.LinkedTextureData._width, mesh.LinkedTextureData._height, textureColor, -10); } Vector2 pos2_0 = Vector2.zero; Vector2 pos2_1 = Vector2.zero; Vector2 pos2_2 = Vector2.zero; Vector3 pos_0 = Vector3.zero; Vector3 pos_1 = Vector3.zero; Vector3 pos_2 = Vector3.zero; Vector2 uv_0 = Vector2.zero; Vector2 uv_1 = Vector2.zero; Vector2 uv_2 = Vector2.zero; //2. 메시를 렌더링하자 if (mesh._indexBuffer.Count >= 3) { if (!isDrawToneOutline) { _matBatch.SetPass_Texture_Normal(color2X, mesh.LinkedTextureData._image, apPortrait.SHADER_TYPE.AlphaBlend); } else { _matBatch.SetPass_ToneColor_Custom(color2X, mesh.LinkedTextureData._image, 0.0f, 0.0f); } _matBatch.SetClippingSize(_glScreenClippingSize); GL.Begin(GL.TRIANGLES); //------------------------------------------ apVertex vert0, vert1, vert2; //Color color0 = Color.black, color1 = Color.black, color2 = Color.black; Color color0 = Color.white, color1 = Color.white, color2 = Color.white; for (int i = 0; i < mesh._indexBuffer.Count; i += 3) { if (i + 2 >= mesh._indexBuffer.Count) { break; } if (mesh._indexBuffer[i + 0] >= mesh._vertexData.Count || mesh._indexBuffer[i + 1] >= mesh._vertexData.Count || mesh._indexBuffer[i + 2] >= mesh._vertexData.Count) { break; } vert0 = mesh._vertexData[mesh._indexBuffer[i + 0]]; vert1 = mesh._vertexData[mesh._indexBuffer[i + 1]]; vert2 = mesh._vertexData[mesh._indexBuffer[i + 2]]; pos2_0 = World2GL(matrix.MultiplyPoint(vert0._pos)); pos2_1 = World2GL(matrix.MultiplyPoint(vert1._pos)); pos2_2 = World2GL(matrix.MultiplyPoint(vert2._pos)); pos_0 = new Vector3(pos2_0.x, pos2_0.y, vert0._zDepth * 0.1f); pos_1 = new Vector3(pos2_1.x, pos2_1.y, vert1._zDepth * 0.5f); pos_2 = new Vector3(pos2_2.x, pos2_2.y, vert2._zDepth * 0.5f); //<<Z값이 반영되었다. uv_0 = mesh._vertexData[mesh._indexBuffer[i + 0]]._uv; uv_1 = mesh._vertexData[mesh._indexBuffer[i + 1]]._uv; uv_2 = mesh._vertexData[mesh._indexBuffer[i + 2]]._uv; GL.Color(color0); GL.TexCoord(uv_0); GL.Vertex(pos_0); // 0 GL.Color(color1); GL.TexCoord(uv_1); GL.Vertex(pos_1); // 1 GL.Color(color2); GL.TexCoord(uv_2); GL.Vertex(pos_2); // 2 //Back Side GL.Color(color2); GL.TexCoord(uv_2); GL.Vertex(pos_2); // 2 GL.Color(color1); GL.TexCoord(uv_1); GL.Vertex(pos_1); // 1 GL.Color(color0); GL.TexCoord(uv_0); GL.Vertex(pos_0); // 0 ////------------------------------------------ } GL.End(); } if (mesh._isPSDParsed && isDrawOutline) { Vector2 pos_LT = matrix.MultiplyPoint(new Vector2(mesh._atlasFromPSD_LT.x, mesh._atlasFromPSD_LT.y)); Vector2 pos_RT = matrix.MultiplyPoint(new Vector2(mesh._atlasFromPSD_RB.x, mesh._atlasFromPSD_LT.y)); Vector2 pos_LB = matrix.MultiplyPoint(new Vector2(mesh._atlasFromPSD_LT.x, mesh._atlasFromPSD_RB.y)); Vector2 pos_RB = matrix.MultiplyPoint(new Vector2(mesh._atlasFromPSD_RB.x, mesh._atlasFromPSD_RB.y)); _matBatch.SetPass_Color(); _matBatch.SetClippingSize(_glScreenClippingSize); GL.Begin(GL.LINES); DrawLine(pos_LT, pos_RT, atlasBorderColor, false); DrawLine(pos_RT, pos_RB, atlasBorderColor, false); DrawLine(pos_RB, pos_LB, atlasBorderColor, false); DrawLine(pos_LB, pos_LT, atlasBorderColor, false); GL.End(); } //외곽선을 그려주자 //float imageWidthHalf = mesh._textureData._width * 0.5f; //float imageHeightHalf = mesh._textureData._height * 0.5f; float imageWidthHalf = mesh.LinkedTextureData._width * 0.5f; float imageHeightHalf = mesh.LinkedTextureData._height * 0.5f; Vector2 pos_TexOutline_LT = matrix.MultiplyPoint(new Vector2(-imageWidthHalf, -imageHeightHalf)); Vector2 pos_TexOutline_RT = matrix.MultiplyPoint(new Vector2(imageWidthHalf, -imageHeightHalf)); Vector2 pos_TexOutline_LB = matrix.MultiplyPoint(new Vector2(-imageWidthHalf, imageHeightHalf)); Vector2 pos_TexOutline_RB = matrix.MultiplyPoint(new Vector2(imageWidthHalf, imageHeightHalf)); _matBatch.SetPass_Color(); _matBatch.SetClippingSize(_glScreenClippingSize); GL.Begin(GL.LINES); DrawLine(pos_TexOutline_LT, pos_TexOutline_RT, atlasBorderColor, false); DrawLine(pos_TexOutline_RT, pos_TexOutline_RB, atlasBorderColor, false); DrawLine(pos_TexOutline_RB, pos_TexOutline_LB, atlasBorderColor, false); DrawLine(pos_TexOutline_LB, pos_TexOutline_LT, atlasBorderColor, false); GL.End(); //3. Edge를 렌더링하자 (전체 / Ouline) if (isDrawEdge) { Vector2 pos0 = Vector2.zero, pos1 = Vector2.zero; if (mesh._edges.Count > 0) { _matBatch.SetPass_Color(); _matBatch.SetClippingSize(_glScreenClippingSize); GL.Begin(GL.LINES); for (int i = 0; i < mesh._edges.Count; i++) { pos0 = matrix.MultiplyPoint(mesh._edges[i]._vert1._pos); pos1 = matrix.MultiplyPoint(mesh._edges[i]._vert2._pos); DrawLine(pos0, pos1, meshEdgeColor, false); } for (int iPoly = 0; iPoly < mesh._polygons.Count; iPoly++) { for (int iHE = 0; iHE < mesh._polygons[iPoly]._hidddenEdges.Count; iHE++) { apMeshEdge hiddenEdge = mesh._polygons[iPoly]._hidddenEdges[iHE]; pos0 = matrix.MultiplyPoint(hiddenEdge._vert1._pos); pos1 = matrix.MultiplyPoint(hiddenEdge._vert2._pos); DrawLine(pos0, pos1, meshHiddenEdgeColor, false); } } GL.End(); } } } catch (Exception ex) { Debug.LogException(ex); } }
private void IsAnyCrossEdgeMultiple(apVertex vert1, apVertex vert2, Vector2 vert2PosIfNull) { if (_mesh == null) { return; } int nVert = _mesh._vertexData.Count; int nEdge = _mesh._edges.Count; Vector2 vert1Local = vert1._pos; Vector2 vert2Local = vert2PosIfNull; if (vert2 != null) { vert2Local = vert2._pos; } apMeshEdge edge = null; apVertex edgeVert1 = null; apVertex edgeVert2 = null; //Vector2 crossPos = Vector2.zero; _tmpEdgeWireMultipleCrossPoints.Clear(); for (int i = 0; i < nEdge; i++) { edge = _mesh._edges[i]; edgeVert1 = edge._vert1; edgeVert2 = edge._vert2; //if (vert2 != null) //{ // if ((vert1 == edgeVert1 && vert2 == edgeVert2) || // (vert1 == edgeVert2 && vert2 == edgeVert1)) // { // //겹치면 : 같은 선분이 있네염 // //교차되었던거 다 무시 // _tmpEdgeWireMultipleCrossPoints.Clear(); // return; // } //} //else //{ // if(vert1 == edgeVert1 || vert1 == edgeVert2) // { // //하나만 겹쳐도 해당 Edge와 교차되지는 않는다. // //교차되었던거 다 무시 // _tmpEdgeWireMultipleCrossPoints.Clear(); // return; // } //} CheckLineIntersetion(edgeVert1._pos, edgeVert2._pos, vert1Local, vert2Local); if (_crossPoint._isIntersetion) { //교차되었다. //단, 교차 포인트가 어느 점 근처라면 SameLine이 아닌 이상 일단 넘어간다. if (_crossPoint._isAnyPointSame) { if (_crossPoint._isSameLine) { //return true;//<아예 겹친다. if (Vector2.Distance(_crossPoint._pos, vert1Local) > 4.0f && Vector2.Distance(_crossPoint._pos, vert2Local) > 4.0f) { _tmpEdgeWireMultipleCrossPoints.Add(_crossPoint._pos); } //return; } //패스 } else { //교차점이 선분 내부에 있다. //만약 교차점이 어느 다른 점과 가까이 있다면 일단 무시할 수 있다. if (_nextVertex != null) { if (Vector2.Distance(_nextVertex._pos, _crossPoint._pos) < nearBias) { continue; } } //교차점이 목표한 선분 내부에 없다면 패스 Vector2 vec2Cross = _crossPoint._pos - vert1Local; Vector2 vec2Req = vert2Local - vert1Local; if (vec2Req.sqrMagnitude > 1.0f && vec2Cross.sqrMagnitude > 1.0f) { float dotProduct = Vector2.Dot(vec2Req, vec2Cross); //if(dotProduct < 0.0f || dotProduct > 1.0f) //{ // continue;//벡터 안에 있는게 아닌것 같다. //} float angle = Vector2.Angle(vec2Req, vec2Cross); //if (dotProduct < 0.0f || angle > 5.0f) //{ // Debug.Log("Cross [Dot : " + dotProduct + " / Angle : " + angle + "]"); //} if (dotProduct < 0.0f) { //Debug.LogError("Cross Out [Dot : " + dotProduct + "]"); continue; } if (vec2Cross.sqrMagnitude > vec2Req.sqrMagnitude) { //Debug.LogError("Cross Out [Length Over : " + vec2Req.magnitude + " >> " + vec2Cross.magnitude + "]"); continue; } //if(angle > 5.0f) //{ // //각도도 다르네요... // continue; //} } if (Vector2.Distance(_crossPoint._pos, vert1Local) > 4.0f && Vector2.Distance(_crossPoint._pos, vert2Local) > 4.0f) { _tmpEdgeWireMultipleCrossPoints.Add(_crossPoint._pos); } //return true; } } else { //교차되지 않았다. //다음 계산 } } //return false; }
// Functions //----------------------------------------------- public void Refresh(apMesh mesh, bool isReset) { //리셋할지 말지 체크 if (!isReset) { if (_mesh != mesh || mesh == null || _nSelectedVert != _editor.VertController.Vertices.Count || _nTotalVert != mesh._vertexData.Count || _nTotalEdge != mesh._edges.Count || !Mathf.Approximately(_offset, _editor._meshTRSOption_MirrorOffset) || _isAddOnRuler != _editor._meshTRSOption_MirrorSnapVertOnRuler ) { isReset = true; } else { if (mesh != null) { if (_isMirrorX != mesh._isMirrorX) { isReset = true; } else if ((mesh._isMirrorX && !Mathf.Approximately(_mirrorPos, mesh._mirrorAxis.x)) || (!mesh._isMirrorX && !Mathf.Approximately(_mirrorPos, mesh._mirrorAxis.y))) { isReset = true; } } } } if (!isReset) { //리스트를 돌면서 //SrcVert의 위치가 미러 축의 (+, -, 0) 중 어디에 들어가는지 확인하자 //하나라도 변경된게 있다면 Reset이다. CloneVertex checkClone = null; for (int i = 0; i < _cloneVerts.Count; i++) { checkClone = _cloneVerts[i]; if (checkClone._compareToMirror != GetMirrorCompare(checkClone._srcVert._pos, true)) { //리셋을 해야할 만큼 위치가 바뀌었다. //Debug.LogError("Mirror 변경됨"); isReset = true; break; } } } if (isReset) { Clear(); if (mesh == null) { return; } if (_editor.VertController.Vertices.Count == 0) { return; } List <apVertex> selectVerts = _editor.VertController.Vertices; List <apVertex> verts = mesh._vertexData; List <apMeshEdge> edges = mesh._edges; _mesh = mesh; _nSelectedVert = selectVerts.Count; _nTotalVert = verts.Count; _nTotalEdge = edges.Count; _offset = _editor._meshTRSOption_MirrorOffset; _isAddOnRuler = _editor._meshTRSOption_MirrorSnapVertOnRuler; _isMirrorX = mesh._isMirrorX; _mirrorPos = mesh._isMirrorX ? mesh._mirrorAxis.x : mesh._mirrorAxis.y; apMeshEdge curEdge = null; apVertex curVert1 = null; apVertex curVert2 = null; for (int iEdge = 0; iEdge < edges.Count; iEdge++) { curEdge = edges[iEdge]; curVert1 = curEdge._vert1; curVert2 = curEdge._vert2; //하나라도 등록되어 있다면 "미러가 될 Edge"로 일단 등록 bool isVert1InList = selectVerts.Contains(curVert1); bool isVert2InList = selectVerts.Contains(curVert2); if (isVert1InList || isVert2InList) { _srcEdges.Add(curEdge); if (isVert1InList) { if (!_srcVerts.Contains(curVert1)) { _srcVerts.Add(curVert1); } if (!_vert2Verts.ContainsKey(curVert1)) { _vert2Verts.Add(curVert1, new List <apVertex>()); } if (!_vert2Verts[curVert1].Contains(curVert2)) { _vert2Verts[curVert1].Add(curVert2); //<Vert1 -> Vert2가 이어져 있음을 등록 } } if (isVert2InList) { if (!_srcVerts.Contains(curVert2)) { _srcVerts.Add(curVert2); } if (!_vert2Verts.ContainsKey(curVert2)) { _vert2Verts.Add(curVert2, new List <apVertex>()); } if (!_vert2Verts[curVert2].Contains(curVert1)) { _vert2Verts[curVert2].Add(curVert1); //<Vert2 -> Vert1가 이어져 있음을 등록 } } //Edge중에서 축에 Cross되는 경우 if (IsCrossAxis(curEdge._vert1._pos, curEdge._vert2._pos)) { Vector2 crossPos = GetCrossPos(curEdge._vert1._pos, curEdge._vert2._pos); _crossVerts.Add(CloneVertex.MakeCrossPoint(crossPos, curEdge) .AddLinkedSrcVert(curEdge._vert1) .AddLinkedSrcVert(curEdge._vert2)); } } } //등록된 Vertex 리스트를 바탕으로 Clone을 만들자 //- 옵션에 따라 바뀐다. //- 일단 Clone간의 연결은 생략하고, Vert -> Clone만 만들자 //- 위치 보정이 중요 //- Cross가 되는 Clone은 여기서 만들지 않는다. apVertex srcVert = null; List <apVertex> linkedVerts = null; apVertex linkedVert = null; for (int iVert = 0; iVert < _srcVerts.Count; iVert++) { srcVert = _srcVerts[iVert]; CloneVertex newCVert = null; if (IsOnAxis(srcVert._pos)) { //Axis 위에 있다면.. newCVert = CloneVertex.MakePointOnAxis(srcVert); } else { //그렇지 않다면 Vector2 mirrorPos = GetMirrorPos(srcVert._pos); newCVert = CloneVertex.MakeMirrorPoint(srcVert, mirrorPos, GetMirrorCompare(srcVert._pos, false)); } //이어진 Vertex 들을 입력하자 linkedVerts = _vert2Verts[srcVert]; for (int iLink = 0; iLink < linkedVerts.Count; iLink++) { linkedVert = linkedVerts[iLink]; newCVert.AddLinkedSrcVert(linkedVert); } _cloneVerts.Add(newCVert); _clone2Vert.Add(newCVert, srcVert); _vert2Clone.Add(srcVert, newCVert); } //CloneVert간에 연결을 하자 CloneVertex cloneVert = null; CloneVertex linkedCloneVert = null; for (int iClone = 0; iClone < _cloneVerts.Count; iClone++) { cloneVert = _cloneVerts[iClone]; for (int iLinkedSrc = 0; iLinkedSrc < cloneVert._linkedSrcVerts.Count; iLinkedSrc++) { srcVert = cloneVert._linkedSrcVerts[iLinkedSrc]; if (_vert2Clone.ContainsKey(srcVert)) { linkedCloneVert = _vert2Clone[srcVert]; cloneVert.AddLinkedCloneVert(linkedCloneVert); } } } //CrossVert를 이용해서 연결 관계를 바꾸자 CloneVertex crossVert = null; CloneVertex linkedCloneVert1 = null; CloneVertex linkedCloneVert2 = null; for (int iCross = 0; iCross < _crossVerts.Count; iCross++) { crossVert = _crossVerts[iCross]; curVert1 = crossVert._srcSplitEdge._vert1; curVert2 = crossVert._srcSplitEdge._vert2; linkedCloneVert1 = null; linkedCloneVert2 = null; if (_vert2Clone.ContainsKey(curVert1)) { linkedCloneVert1 = _vert2Clone[curVert1]; crossVert.AddLinkedCloneVert(linkedCloneVert1); } if (_vert2Clone.ContainsKey(curVert2)) { linkedCloneVert2 = _vert2Clone[curVert2]; crossVert.AddLinkedCloneVert(linkedCloneVert2); } if (linkedCloneVert1 != null) { linkedCloneVert1.AddLinkedCloneVert(crossVert); //만약 반대쪽이 연결된 상태라면 연결을 끊는다. if (linkedCloneVert2 != null) { linkedCloneVert1.RemoveLinkedCloneVert(linkedCloneVert2); } } if (linkedCloneVert2 != null) { linkedCloneVert2.AddLinkedCloneVert(crossVert); //만약 반대쪽이 연결된 상태라면 연결을 끊는다. if (linkedCloneVert1 != null) { linkedCloneVert2.RemoveLinkedCloneVert(linkedCloneVert1); } } } //CloneEdge를 완성한다. >> _cloneEdges //빠른 중복 CloneVertex cloneVert1 = null; CloneVertex cloneVert2 = null; Dictionary <CloneVertex, List <CloneVertex> > edgedVertPairs = new Dictionary <CloneVertex, List <CloneVertex> >(); for (int iClone = 0; iClone < _cloneVerts.Count; iClone++) { cloneVert = _cloneVerts[iClone]; for (int iLinkClone = 0; iLinkClone < cloneVert._linkedCloneVerts.Count; iLinkClone++) { linkedCloneVert = cloneVert._linkedCloneVerts[iLinkClone]; if (cloneVert._index < linkedCloneVert._index) { cloneVert1 = cloneVert; cloneVert2 = linkedCloneVert; } else { cloneVert1 = linkedCloneVert; cloneVert2 = cloneVert; } bool isExisted = false; if (edgedVertPairs.ContainsKey(cloneVert1)) { if (edgedVertPairs[cloneVert1].Contains(cloneVert2)) { isExisted = true; } else { edgedVertPairs[cloneVert1].Add(cloneVert2); } } else { edgedVertPairs.Add(cloneVert1, new List <CloneVertex>()); edgedVertPairs[cloneVert1].Add(cloneVert2); } if (!isExisted) { _cloneEdges.Add(new CloneEdge(cloneVert1, cloneVert2)); } } } } else { //위치만 갱신하자 CloneVertex curCloneVert = null; for (int iClone = 0; iClone < _cloneVerts.Count; iClone++) { curCloneVert = _cloneVerts[iClone]; if (!curCloneVert._isOnAxis) { curCloneVert._pos = GetMirrorPos(curCloneVert._srcVert._pos); } else { curCloneVert._pos = curCloneVert._srcVert._pos; } } for (int iClone = 0; iClone < _crossVerts.Count; iClone++) { curCloneVert = _crossVerts[iClone]; if (curCloneVert._linkedSrcVerts.Count < 2) { continue; } Vector2 crossPos = GetCrossPos(curCloneVert._linkedSrcVerts[0]._pos, curCloneVert._linkedSrcVerts[1]._pos); curCloneVert._pos = crossPos; } } }
public bool IsEdgeContain(apMeshEdge edge) { return(_edges.Contains(edge)); }
public void Link(apMesh mesh) { //Mesh에 속한 Vert와 Edge는 초기화 후 ID와 연결해준다. //그 외에는 내부 Link를 호출한다. _verts.Clear(); _edges.Clear(); for (int i = 0; i < _vertIDs.Count; i++) { apVertex vert = mesh.GetVertexByUniqueID(_vertIDs[i]); if (vert != null) { _verts.Add(vert); } else { //?? 없는 Vert다. _vertIDs[i] = -1; } } _vertIDs.RemoveAll(delegate(int a) { return(a < 0); }); for (int i = 0; i < _edgeIDs.Count; i++) { apMeshEdge edge = mesh.GetEdgeByUniqueID(_edgeIDs[i]._ID1, _edgeIDs[i]._ID2); if (edge != null) { _edges.Add(edge); } else { _edgeIDs[i]._ID1 = -1; _edgeIDs[i]._ID2 = -1; } } _edgeIDs.RemoveAll(delegate(IDPair a) { return(a._ID1 < 0 || a._ID2 < 0); }); //나머지도 링크를 하자 for (int i = 0; i < _hidddenEdges.Count; i++) { apMeshEdge hiddenEdge = _hidddenEdges[i]; apVertex vert1 = mesh.GetVertexByUniqueID(hiddenEdge._vertID_1); apVertex vert2 = mesh.GetVertexByUniqueID(hiddenEdge._vertID_2); hiddenEdge.Link(vert1, vert2); } _hidddenEdges.RemoveAll(delegate(apMeshEdge a) { return(a._vert1 == null || a._vert2 == null); }); for (int i = 0; i < _tris.Count; i++) { apMeshTri tri = _tris[i]; apVertex vert1 = mesh.GetVertexByUniqueID(tri._vertIDs[0]); apVertex vert2 = mesh.GetVertexByUniqueID(tri._vertIDs[1]); apVertex vert3 = mesh.GetVertexByUniqueID(tri._vertIDs[2]); tri.Link(vert1, vert2, vert3); } _tris.RemoveAll(delegate(apMeshTri a) { return(a._verts[0] == null || a._verts[1] == null || a._verts[2] == null); }); }
public static bool IsEdgeCross(apMeshEdge edge1, apMeshEdge edge2) { return(IsEdgeCross(edge1._vert1, edge1._vert2, edge2._vert1, edge2._vert2)); }
public bool TurnHiddenEdge(apMeshEdge hiddenEdge) { if (!_hidddenEdges.Contains(hiddenEdge)) { Debug.LogError("Not Contains Hidden Edge"); return(false); } //List<apMeshEdge> allEdges = new List<apMeshEdge>(); //for (int i = 0; i < _edges.Count; i++) //{ // allEdges.Add(_edges[i]); //} //for (int i = 0; i < _hidddenEdges.Count; i++) //{ // allEdges.Add(_hidddenEdges[i]); //} List <apMeshTri> containTris = _tris.FindAll(delegate(apMeshTri a) { return(a.IsIncludeEdge(hiddenEdge)); }); if (containTris.Count != 2) { //회전이 불가능하다 Debug.LogError("Tri Count is Not 2 : " + containTris.Count); return(false); } apVertex[] newVerts = new apVertex[2]; for (int i = 0; i < 2; i++) { apMeshTri curTri = containTris[i]; if (curTri._verts[0] != hiddenEdge._vert1 && curTri._verts[0] != hiddenEdge._vert2) { newVerts[i] = curTri._verts[0]; } else if (curTri._verts[1] != hiddenEdge._vert1 && curTri._verts[1] != hiddenEdge._vert2) { newVerts[i] = curTri._verts[1]; } else if (curTri._verts[2] != hiddenEdge._vert1 && curTri._verts[2] != hiddenEdge._vert2) { newVerts[i] = curTri._verts[2]; } else { newVerts[i] = null; } } if (newVerts[0] != null && newVerts[1] != null && newVerts[0] != newVerts[1]) { //새로운 엣지를 넣고 apMeshEdge newHidden = new apMeshEdge(newVerts[0], newVerts[1]); newHidden._isHidden = true; _hidddenEdges.Add(newHidden); //Debug.LogWarning("Vertex Turn [" // + hiddenEdge._vert1._index + ", " + hiddenEdge._vert2._index + "] -> [" // + newHidden._vert1._index + ", " + newHidden._vert2._index + "]"); //현재 엣지를 지우자 _hidddenEdges.Remove(hiddenEdge); MakeTriangles(); } else { Debug.LogError("Vertex is Error"); } return(true); }
public void MakeHiddenEdgeAndTri() { int nVert = _verts.Count; int nNeedHiddenEdge = nVert - 3; int nNeedTri = nVert - 2; if (_hidddenEdges.Count == nNeedHiddenEdge && _tris.Count == nNeedTri) { return; } _hidddenEdges.Clear(); //Debug.Log("Verts : " + nVert + " / Hidden : " + nNeedHiddenEdge + " / Tri : " + nNeedTri); List <AutoHiddenEdgeData> hiddenData = new List <AutoHiddenEdgeData>(); if (nNeedHiddenEdge > 0) { //Debug.Log("히든 엣지 필요 개수 : " + nNeedHiddenEdge); for (int iBaseVert = 0; iBaseVert < nVert; iBaseVert++) { apVertex baseVert = _verts[iBaseVert]; //직접 연결되지 않은 Edge를 찾자 for (int iNext = 0; iNext < nVert; iNext++) { apVertex nextVert = _verts[iNext]; if (nextVert == baseVert) { continue; } //Edge가 있는가 bool isExistEdge = _edges.Exists(delegate(apMeshEdge a) { return(a.IsSameEdge(baseVert, nextVert)); }); if (isExistEdge) { continue; } if (hiddenData.Exists(delegate(AutoHiddenEdgeData a) { return((a._vert1 == baseVert && a._vert2 == nextVert) || (a._vert2 == baseVert && a._vert1 == nextVert)); })) { continue; } //없다 -> HiddenEdge 대상이다. //다른 HiddenEdge와 겹치지 않는지 체크한다. bool isAnyCross = false; for (int iHide = 0; iHide < _hidddenEdges.Count; iHide++) { apMeshEdge hiddenEdge = _hidddenEdges[iHide]; if (hiddenEdge.IsSameEdge(baseVert, nextVert)) { isAnyCross = true; break; } if (apMeshEdge.IsEdgeCross(hiddenEdge._vert1, hiddenEdge._vert2, baseVert, nextVert)) { isAnyCross = true; break; } } if (!isAnyCross) { //교차되는 Hidden Edge가 없다. //Hidden Edge를 만들쟈! //수정 => 일단 Hidden Edge "대상"에 넣자 AutoHiddenEdgeData newHiddenData = new AutoHiddenEdgeData(baseVert, nextVert); //다른 Edge와 비교하여 Angle을 넣어주자 for (int iEdge = 0; iEdge < _edges.Count; iEdge++) { apMeshEdge edge = _edges[iEdge]; float angle = Vector2.Angle(edge._vert2._pos - edge._vert1._pos, nextVert._pos - baseVert._pos); if (angle > 90.0f) { angle = 180.0f - angle; } newHiddenData.SetEdgeAngle(angle); } hiddenData.Add(newHiddenData); //Debug.Log("Make Hidden Edge"); } } } hiddenData.Sort(delegate(AutoHiddenEdgeData a, AutoHiddenEdgeData b) { return(b.Score - a.Score); }); for (int iData = 0; iData < hiddenData.Count; iData++) { AutoHiddenEdgeData data = hiddenData[iData]; //다른 HiddenEdge와 겹치지 않는지 체크한다. bool isAnyCross = false; for (int iHide = 0; iHide < _hidddenEdges.Count; iHide++) { apMeshEdge hiddenEdge = _hidddenEdges[iHide]; if (hiddenEdge.IsSameEdge(data._vert1, data._vert2)) { isAnyCross = true; break; } if (apMeshEdge.IsEdgeCross(hiddenEdge._vert1, hiddenEdge._vert2, data._vert1, data._vert2)) { isAnyCross = true; break; } } if (isAnyCross) { continue; } apMeshEdge newHiddenEdge = new apMeshEdge(data._vert1, data._vert2); newHiddenEdge._isHidden = true; _hidddenEdges.Add(newHiddenEdge); if (_hidddenEdges.Count >= nNeedHiddenEdge) { break; } } if (_hidddenEdges.Count < nNeedHiddenEdge) { //오잉? 다 입력되지 않았네요. 그냥 한번 넣어봅시다. for (int iBaseVert = 0; iBaseVert < nVert; iBaseVert++) { apVertex baseVert = _verts[iBaseVert]; //직접 연결되지 않은 Edge를 찾자 for (int iNext = 0; iNext < nVert; iNext++) { apVertex nextVert = _verts[iNext]; if (nextVert == baseVert) { continue; } //Edge가 있는가 bool isExistEdge = _edges.Exists(delegate(apMeshEdge a) { return(a.IsSameEdge(baseVert, nextVert)); }); if (isExistEdge) { continue; } //없다 -> HiddenEdge 대상이다. //다른 HiddenEdge와 겹치지 않는지 체크한다. bool isAnyCross = false; for (int iHide = 0; iHide < _hidddenEdges.Count; iHide++) { apMeshEdge hiddenEdge = _hidddenEdges[iHide]; if (hiddenEdge.IsSameEdge(baseVert, nextVert)) { isAnyCross = true; break; } if (apMeshEdge.IsEdgeCross(hiddenEdge._vert1, hiddenEdge._vert2, baseVert, nextVert)) { isAnyCross = true; break; } } if (isAnyCross) { continue; } apMeshEdge newHiddenEdge = new apMeshEdge(baseVert, nextVert); newHiddenEdge._isHidden = true; _hidddenEdges.Add(newHiddenEdge); if (_hidddenEdges.Count >= nNeedHiddenEdge) { break; } } } } //Debug.LogWarning("만들어진 히든 엣지 : " + _hidddenEdges.Count); } //Hidden Edge까지 추가했다면.. //이제 내부에 Tri를 만들어주자 //이건 겹치는건 체크하지 않는다. //Hidden을 제외하고는 //1Edge -> 1Tri이며, //이미 Tri에 포함된 Edge는 제외한다. _tris.Clear(); if (nNeedTri > 0) { MakeTriangles(); } }
public static CrossCheckResult IsEdgeCrossWithResult(apMeshEdge edge, Vector2 edge2A, Vector2 edge2B) { CrossCheckResult.I.Init(); Vector2 edge1A = edge._vert1._pos; Vector2 edge1B = edge._vert2._pos; //만약 어떤 점이 겹친 상태라면 일단 겹친 점에 대한 정보를 넣어준다. if (Vector2.Distance(edge1A, edge2A) < zeroBias || Vector2.Distance(edge1A, edge2B) < zeroBias) { //Vert1 에 겹친다. CrossCheckResult.I.SetSameVertexResult(edge._vert1); return(CrossCheckResult.I); } else if (Vector2.Distance(edge1B, edge2A) < zeroBias || Vector2.Distance(edge1B, edge2B) < zeroBias) { //Vert2 에 겹친다. CrossCheckResult.I.SetSameVertexResult(edge._vert2); return(CrossCheckResult.I); } float dX_1 = edge1B.x - edge1A.x; float dY_1 = edge1B.y - edge1A.y; float dX_2 = edge2B.x - edge2A.x; float dY_2 = edge2B.y - edge2A.y; float a1 = 0.0f; float a2 = 0.0f; float b1 = 0.0f; float b2 = 0.0f; float x1_Min = Mathf.Min(edge1A.x, edge1B.x); float x1_Max = Mathf.Max(edge1A.x, edge1B.x); float y1_Min = Mathf.Min(edge1A.y, edge1B.y); float y1_Max = Mathf.Max(edge1A.y, edge1B.y); float x2_Min = Mathf.Min(edge2A.x, edge2B.x); float x2_Max = Mathf.Max(edge2A.x, edge2B.x); float y2_Min = Mathf.Min(edge2A.y, edge2B.y); float y2_Max = Mathf.Max(edge2A.y, edge2B.y); //수직/수평에 따라 다르게 처리 if (Mathf.Abs(dX_1) < zeroBias * 0.01f) { float X1 = (edge1A.x + edge1B.x) * 0.5f; //Line 1이 수직일 때 if (Mathf.Abs(dX_2) < zeroBias * 0.01f) { //Line 2도 같이 수직일 때 //수직 + 수직 //x가 같으면 [겹침] (y범위 비교) //그 외에는 [평행] float X2 = (edge2A.x + edge2B.x) * 0.5f; if (Mathf.Abs(X1 - X2) < zeroBias * 0.01f) { //Y 영역이 겹치는가 [Y영역이 겹치면 겹침] if (IsAreaIntersection(y1_Min, y1_Max, y2_Min, y2_Max)) { CrossCheckResult.I.SetSameLine((edge1A + edge1B) * 0.5f); return(CrossCheckResult.I); } } } else { //Line 2는 수평이나 기울기가 있을 때 //Line1의 x 범위에서 y 안에 들면 [교차] //Line1의 x 범위 밖이거나 y 범위 밖에 있으면 [교차하지 않음] if (x2_Min <= X1 && X1 <= x2_Max) { a2 = dY_2 / dX_2; b2 = edge2A.y - edge2A.x * a2; float Yresult = a2 * X1 + b2; if (y1_Min <= Yresult && Yresult <= y1_Max) { //[교차] CrossCheckResult.I.SetCrossResult(new Vector2(X1, Yresult)); return(CrossCheckResult.I); } } } } else { //Line 1이 수평 또는 기울기가 있을 때 if (Mathf.Abs(dX_2) < zeroBias * 0.01f) { //Line 2가 수직일 때 //Line2를 기준으로 x, y범위 비교후 Y 체크 [교차] //범위 밖이면 [교차하지 않음] float X2 = (edge2A.x + edge2B.x) * 0.5f; if (x1_Min <= X2 && X2 <= x1_Max) { a1 = dY_1 / dX_1; b1 = edge1A.y - edge1A.x * a1; float Yresult = a1 * X2 + b1; if (y2_Min <= Yresult && Yresult <= y2_Max) { //[교차] CrossCheckResult.I.SetCrossResult(new Vector2(X2, Yresult)); return(CrossCheckResult.I); } } } else { //Line 2는 수평이나 기울기가 있을 때 //X 범위 비교후 //대입법 이용하여 체크하면 [교차] if (IsAreaIntersection(x1_Min, x1_Max, x2_Min, x2_Max)) { a1 = dY_1 / dX_1; b1 = edge1A.y - edge1A.x * a1; a2 = dY_2 / dX_2; b2 = edge2A.y - edge2A.x * a2; float Yparam1 = a2 - a1; float Yparam2 = (a2 * b1) - (a1 * b2); if (Mathf.Abs(Yparam1) < zeroBias * 0.01f) { //기울기가 같을때 //b도 같아야한다. if (Mathf.Abs(Yparam2) < zeroBias * 0.01f) { //[일치] CrossCheckResult.I.SetSameLine((edge1A + edge1B) * 0.5f); return(CrossCheckResult.I); } } else { //기울기가 다를때 float Yresult = Yparam2 / Yparam1; //교차점의 위치를 확인한다. if (y1_Min <= Yresult && Yresult <= y1_Max && y2_Min <= Yresult && Yresult <= y2_Max) { float Xresult = (Yresult - b1) / a1; CrossCheckResult.I.SetCrossResult(new Vector2(Xresult, Yresult)); return(CrossCheckResult.I); } } } } } //return _crossPoint; return(null); }