/// <summary> /// Quitar poligono de la lista /// </summary> public void removePolygon(EditPolyPolygon p) { for (int i = 0; i < faces.Count; i++) { if (faces[i] == p) { faces.RemoveAt(i); break; } } }
/// <summary> /// Quitar poligono de la lista /// </summary> public void removePolygon(EditPolyPolygon p) { for (int i = 0; i < faces.Count; i++) { if (faces[i] == p) { faces.RemoveAt(i); break; } } }
/// <summary> /// Tomar un mesh cargar todas las estructuras internas necesarias para poder editarlo /// </summary> private void loadMesh(TgcMesh origMesh) { //Obtener vertices del mesh this.mesh = origMesh; List<EditPolyVertex> origVertices = getMeshOriginalVertexData(origMesh); int origTriCount = origVertices.Count / 3; //Iterar sobre los triangulos y generar data auxiliar unificada vertices = new List<EditPolyVertex>(); edges = new List<EditPolyEdge>(); polygons = new List<EditPolyPolygon>(); indexBuffer = new short[origTriCount * 3]; int[] attributeBuffer = origMesh.D3dMesh.LockAttributeBufferArray(LockFlags.ReadOnly); origMesh.D3dMesh.UnlockAttributeBuffer(attributeBuffer); for (int i = 0; i < origTriCount; i++) { EditPolyVertex v1 = origVertices[i * 3]; EditPolyVertex v2 = origVertices[i * 3 + 1]; EditPolyVertex v3 = origVertices[i * 3 + 2]; //Agregar vertices a la lista, si es que son nuevos int v1Idx = EditablePolyUtils.addVertexToListIfUnique(vertices, v1); int v2Idx = EditablePolyUtils.addVertexToListIfUnique(vertices, v2); int v3Idx = EditablePolyUtils.addVertexToListIfUnique(vertices, v3); v1 = vertices[v1Idx]; v2 = vertices[v2Idx]; v3 = vertices[v3Idx]; //Crear edges EditPolyEdge e1 = new EditPolyEdge(); e1.a = v1; e1.b = v2; EditPolyEdge e2 = new EditPolyEdge(); e2.a = v2; e2.b = v3; EditPolyEdge e3 = new EditPolyEdge(); e3.a = v3; e3.b = v1; //Crear poligono para este triangulo EditPolyPolygon p = new EditPolyPolygon(); p.vertices = new List<EditPolyVertex>(); p.vertices.Add(v1); p.vertices.Add(v2); p.vertices.Add(v3); p.edges = new List<EditPolyEdge>(); p.edges.Add(e1); p.edges.Add(e2); p.edges.Add(e3); p.vbTriangles = new List<int>(); p.vbTriangles.Add(i * 3); p.plane = Plane.FromPoints(v1.position, v2.position, v3.position); p.plane.Normalize(); p.matId = attributeBuffer[i]; //Agregar triangulo al index buffer indexBuffer[i * 3] = (short)v1Idx; indexBuffer[i * 3 + 1] = (short)v2Idx; indexBuffer[i * 3 + 2] = (short)v3Idx; //Agregar a lista de poligonos polygons.Add(p); /* //Buscar si hay un poligono ya existente al cual sumarnos (coplanar y que compartan una arista) EditPolyPolygon coplanarP = null; for (int j = 0; j < polygons.Count; j++) { //Coplanares y con igual material ID EditPolyPolygon p0 = polygons[j]; if (p0.matId == p.matId && EditablePolyUtils.samePlane(p0.plane, p.plane)) { //Buscar si tienen una arista igual int p0SharedEdgeIdx; int pSharedEdgeIdx; if (EditablePolyUtils.findShareEdgeBetweenPolygons(p0, p, out p0SharedEdgeIdx, out pSharedEdgeIdx)) { //Obtener el tercer vertice del triangulo que no es parte de la arista compartida EditPolyEdge sharedEdge = p0.edges[p0SharedEdgeIdx]; EditPolyVertex thirdVert; if (p.vertices[0] != sharedEdge.a && p.vertices[0] != sharedEdge.b) thirdVert = p.vertices[0]; else if (p.vertices[1] != sharedEdge.a && p.vertices[1] != sharedEdge.b) thirdVert = p.vertices[1]; else thirdVert = p.vertices[2]; //Agregar el tercer vertice al poligno existente EditablePolyUtils.addVertexToPolygon(p0, sharedEdge, thirdVert); //Quitar arista compartida p0.edges.Remove(sharedEdge); //Agregar al poligono dos nuevas aristas que conectar los extremos de la arista compartida hacia el tercer vertice EditPolyEdge newPolEdge1 = new EditPolyEdge(); newPolEdge1.a = sharedEdge.a; newPolEdge1.b = thirdVert; p0.edges.Add(newPolEdge1); EditPolyEdge newPolEdge2 = new EditPolyEdge(); newPolEdge2.a = thirdVert; newPolEdge2.b = sharedEdge.b; p0.edges.Add(newPolEdge2); //Agregar indice de triangulo del vertexBuffer que se sumo al poligono p0.vbTriangles.Add(p.vbTriangles[0]); coplanarP = p0; } } } //Es un nuevo poligono, agregarlo if (coplanarP == null) { polygons.Add(p); } */ } //Unificar aristas de los poligonos foreach (EditPolyPolygon p in polygons) { for (int i = 0; i < p.edges.Count; i++) { bool newEdgeAdded; int eIdx = EditablePolyUtils.addEdgeToListIfUnique(edges, p.edges[i], out newEdgeAdded); EditPolyEdge e = edges[eIdx]; //Nueva arista incorporada a la lista if (newEdgeAdded) { e.faces = new List<EditPolyPolygon>(); //Agregar referencia a vertices que usan la arista e.a.edges.Add(e); e.b.edges.Add(e); } //Se usa arista existente de la lista else { //Reemplazar en poligono por la nueva p.edges[i] = e; } //Indicar a la arista que pertenece al poligono actual e.faces.Add(p); } } setDirtyValues(false); }
/// <summary> /// Eliminar poligono /// </summary> private void deletePolygon(EditPolyPolygon p) { //Quitar triangulos de index buffer int vertexToDelete = p.vbTriangles.Count * 3; short[] newIndexBuffer = new short[indexBuffer.Length - vertexToDelete]; int w = 0; for (int i = 0; i < indexBuffer.Length; i += 3) { bool toDelete = false; for (int j = 0; j < p.vbTriangles.Count; j++) { if (i == p.vbTriangles[j]) { toDelete = true; break; } } if(toDelete) { //Ajustar todos los indices de triangulos del resto de los poligonos existentes foreach (EditPolyPolygon poly in polygons) { if(poly != p) { for (int j = 0; j < poly.vbTriangles.Count; j++) { if(poly.vbTriangles[j] >= i) { poly.vbTriangles[j] -= 3; } } } } } else { newIndexBuffer[w++] = indexBuffer[i]; newIndexBuffer[w++] = indexBuffer[i + 1]; newIndexBuffer[w++] = indexBuffer[i + 2]; } } indexBuffer = newIndexBuffer; //Quitar referencia a aristas foreach (EditPolyEdge edge in p.edges) { edge.removePolygon(p); } //Eliminar aristas que quedaron aisladas foreach (EditPolyEdge edge in p.edges) { if (edge.faces.Count == 0) { deleteEdge(edge); } } //Quitar de lista de poligonos for (int i = 0; i < polygons.Count; i++) { if (polygons[i] == p) { polygons.RemoveAt(i); break; } } //Registrar triangulos que se eliminaron (apuntando al indice del primer vertice de cada triangulo) //Se registran el valor original al que apuntaba el triangulo antes de haber borrado nada int currentDeletedCount = deletedTriangles.Count; for (int i = 0; i < p.vbTriangles.Count; i++) { int triDelIdx = p.vbTriangles[i]; for (int j = 0; j < currentDeletedCount; j++) { if (triDelIdx < deletedTriangles[j]) { break; } triDelIdx += 3; } deletedTriangles.Add(triDelIdx); } deletedTriangles.Sort(); }
/// <summary> /// Busca si ambos poligonos tienen una arista igual. /// Si encontro retorna el indice de la arista igual de cada poligono. /// </summary> public static bool findShareEdgeBetweenPolygons(EditPolyPolygon p1, EditPolyPolygon p2, out int p1Edge, out int p2Edge) { for (int i = 0; i < p1.edges.Count; i++) { for (int j = 0; j < p2.edges.Count; j++) { if (EditablePolyUtils.sameEdge(p1.edges[i], p2.edges[j])) { p1Edge = i; p2Edge = j; return true; } } } p1Edge = -1; p2Edge = -1; return false; }
/* /// <summary> /// Filtrar todas las aristas que tiene un poligono y dejarle solo las que son parte del borde del poligono /// (Se quitan todas las aristas interiores) /// </summary> public static void computePolygonExternalEdges(Polygon p) { if (p.vertices.Count == 3) return; Vector3 planeNorm = p.getNormal(); List<Edge> externalEdges = new List<Edge>(); foreach (Edge e in p.edges) { //Half-plane entre la arista y la normal del poligono Vector3 vec = e.b.position - e.a.position; Vector3 n = Vector3.Cross(planeNorm, vec); Plane halfPlane = Plane.FromPointNormal(e.a.position, n); //Checkear el signo de todos los demas vertices del poligono bool first = true; TgcCollisionUtils.PointPlaneResult lastR = TgcCollisionUtils.PointPlaneResult.COINCIDENT; bool inside = false; foreach (Vertex v in p.vertices) { if(v.vbIndex != e.a.vbIndex && v.vbIndex != e.b.vbIndex ) { TgcCollisionUtils.PointPlaneResult r = TgcCollisionUtils.classifyPointPlane(v.position, halfPlane); if(first) { first = false; lastR = r; } else if(r != lastR) { inside = true; break; } } } if(!inside) { externalEdges.Add(e); } } p.edges = externalEdges; } /// <summary> /// Ordenar los vertices del poligono en base al recorrido de sus aristas externas /// </summary> public static void sortPolygonVertices(Polygon p) { if (p.vertices.Count == 3) return; List<Vertex> sortedVertices = new List<Vertex>(); Edge lastEdge = p.edges[0]; for (int i = 1; i < p.edges.Count; i++) { sortedVertices.Add(lastEdge.a); bool found = false; foreach (Edge e in p.edges) { if(lastEdge.b.vbIndex == e.a.vbIndex) { lastEdge = e; found = true; break; } } if(!found) throw new Exception("No se pudo recorrer aristas de poligono en loop. Poligono: " + p); } sortedVertices.Add(lastEdge.a); p.vertices = sortedVertices; } */ /// <summary> /// Agregar un vertice a un poligono existente, ubicandolo en el medio de los dos vertices de la arista que compartian entre si /// </summary> public static void addVertexToPolygon(EditPolyPolygon p, EditPolyEdge sharedEdge, EditPolyVertex newV) { for (int i = 0; i < p.vertices.Count; i++) { if (p.vertices[i].vbIndex == sharedEdge.a.vbIndex) { p.vertices.Add(null); for (int j = p.vertices.Count - 2; j >= i + 1 ; j--) { p.vertices[j + 1] = p.vertices[j]; } p.vertices[i + 1] = newV; break; } } }