/// <summary> /// Eliminar un vertice /// </summary> private void deleteVertex(EditPolyVertex v) { //Quitar referencia de todas las aristas que lo usan foreach (var edge in v.edges) { edge.a = null; edge.b = null; } //Eliminar aristas foreach (var edge in v.edges) { deleteEdge(edge); } //Quitar vertice de lista de vertices Vertices.RemoveAt(v.vbIndex); //Shift de vertex buffer for (var i = 0; i < Vertices.Count; i++) { Vertices[i].vbIndex = i; } //Ajustar indices en index buffer for (var i = 0; i < IndexBuffer.Length; i++) { if (IndexBuffer[i] >= v.vbIndex) { IndexBuffer[i]--; } } }
/// <summary> /// Obtener la lista de vertices originales del mesh /// </summary> private List <EditPolyVertex> getMeshOriginalVertexData(TgcMesh origMesh) { var origVertices = new List <EditPolyVertex>(); switch (origMesh.RenderType) { case TgcMesh.MeshRenderType.VERTEX_COLOR: var verts1 = (TgcSceneLoader.VertexColorVertex[])origMesh.D3dMesh.LockVertexBuffer( typeof(TgcSceneLoader.VertexColorVertex), LockFlags.ReadOnly, origMesh.D3dMesh.NumberVertices); for (var i = 0; i < verts1.Length; i++) { var v = new EditPolyVertex(); v.position = verts1[i].Position; /*v.normal = verts1[i].Normal; * v.color = verts1[i].Color;*/ origVertices.Add(v); } origMesh.D3dMesh.UnlockVertexBuffer(); break; case TgcMesh.MeshRenderType.DIFFUSE_MAP: var verts2 = (TgcSceneLoader.DiffuseMapVertex[])origMesh.D3dMesh.LockVertexBuffer( typeof(TgcSceneLoader.DiffuseMapVertex), LockFlags.ReadOnly, origMesh.D3dMesh.NumberVertices); for (var i = 0; i < verts2.Length; i++) { var v = new EditPolyVertex(); v.position = verts2[i].Position; /*v.normal = verts2[i].Normal; * v.texCoords = new TGCVector2(verts2[i].Tu, verts2[i].Tv); * v.color = verts2[i].Color;*/ origVertices.Add(v); } origMesh.D3dMesh.UnlockVertexBuffer(); break; case TgcMesh.MeshRenderType.DIFFUSE_MAP_AND_LIGHTMAP: var verts3 = (TgcSceneLoader.DiffuseMapAndLightmapVertex[])origMesh.D3dMesh.LockVertexBuffer( typeof(TgcSceneLoader.DiffuseMapAndLightmapVertex), LockFlags.ReadOnly, origMesh.D3dMesh.NumberVertices); for (var i = 0; i < verts3.Length; i++) { var v = new EditPolyVertex(); v.position = verts3[i].Position; /*v.normal = verts3[i].Normal; * v.texCoords = new TGCVector2(verts3[i].Tu0, verts3[i].Tv0); * v.color = verts3[i].Color; * v.texCoords2 = new TGCVector2(verts3[i].Tu1, verts3[i].Tv1);*/ origVertices.Add(v); } origMesh.D3dMesh.UnlockVertexBuffer(); break; } return(origVertices); }
/// <summary> /// Agrega un nuevo vertice a la lista si es que ya no hay otro igual. /// Devuelve el indice del nuevo vertice o del que ya estaba. /// </summary> public static int addVertexToListIfUnique(List <EditPolyVertex> vertices, EditPolyVertex v) { for (int i = 0; i < vertices.Count; i++) { if (EditablePolyUtils.sameVextex(vertices[i], v)) { return(i); } } v.vbIndex = vertices.Count; v.edges = new List <EditPolyEdge>(); vertices.Add(v); return(v.vbIndex); }
/// <summary> /// Actualizar estructuras internas en base a mesh original. /// Cuando se vuelve a entrar al modo EditablePoly luego de la primera vez. /// </summary> public void updateValuesFromMesh(TgcMesh mesh) { this.mesh = mesh; List <EditPolyVertex> origVertices = getMeshOriginalVertexData(mesh); for (int i = 0; i < origVertices.Count; i++) { EditPolyVertex origV = origVertices[i]; EditPolyVertex v = vertices[indexBuffer[i]]; v.position = origV.position; /*v.normal = origV.normal; * v.color = origV.color; * v.texCoords = origV.texCoords; * v.texCoords2 = origV.texCoords2;*/ } dirtyValues = true; }
/// <summary> /// Indica si dos vertices son iguales /// </summary> /// <returns></returns> public static bool sameVextex(EditPolyVertex a, EditPolyVertex b) { return(equalsVector3(a.position, b.position)); }
/* * /// <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; } } }
/// <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); }