def triangulate(vertices): t = Triangulator() for i, v in enumerate(vertices): t.add_vertex(v) t.add_polygon_vertex(i) t.triangulate() # Make sure that the result is consistent by starting each triangle with # the lowest index value. That makes it easier to use predetermined values # in the test cases. result = set() for n in range(t.get_num_triangles()): # Switch to lowest matching index value in case of duplicates. v0 = vertices.index(vertices[t.get_triangle_v0(n)]) v1 = vertices.index(vertices[t.get_triangle_v1(n)]) v2 = vertices.index(vertices[t.get_triangle_v2(n)]) if v1 < v0: v0, v1, v2 = v1, v2, v0 if v1 < v0: v0, v1, v2 = v1, v2, v0 result.add((v0, v1, v2)) return result
def create_plane_mesh(vertices, vertices_floor, textures, texture_floor, texture_ceiling, delta_height, ignore_ceiling=False): # create mesh for 3D floorplan visualization triangles = [] triangle_uvs = [] # the number of vertical walls num_walls = len(vertices) # 1. vertical wall (always rectangle) num_vertices = 0 for i in range(len(vertices)): # hardcode triangles for each vertical wall triangle = np.array([[0, 2, 1], [2, 0, 3]]) triangles.append(triangle + num_vertices) num_vertices += 4 triangle_uv = np.array( [ [i / (num_walls + 2), 0], [i / (num_walls + 2), 1], [(i+1) / (num_walls + 2), 1], [(i+1) / (num_walls + 2), 0] ], dtype=np.float32 ) triangle_uvs.append(triangle_uv) # 2. floor and ceiling # Since the floor and ceiling may not be a rectangle, triangulate the polygon first. tri = Triangulator() for i in range(len(vertices_floor)): tri.add_vertex(vertices_floor[i, 0], vertices_floor[i, 1]) for i in range(len(vertices_floor)): tri.add_polygon_vertex(i) tri.triangulate() # polygon triangulation triangle = [] for i in range(tri.getNumTriangles()): triangle.append([tri.get_triangle_v0(i), tri.get_triangle_v1(i), tri.get_triangle_v2(i)]) triangle = np.array(triangle) # add triangles for floor and ceiling triangles.append(triangle + num_vertices) num_vertices += len(np.unique(triangle)) if not ignore_ceiling: triangles.append(triangle + num_vertices) # texture for floor and ceiling vertices_floor_min = np.min(vertices_floor[:, :2], axis=0) vertices_floor_max = np.max(vertices_floor[:, :2], axis=0) # normalize to [0, 1] triangle_uv = (vertices_floor[:, :2] - vertices_floor_min) / (vertices_floor_max - vertices_floor_min) triangle_uv[:, 0] = (triangle_uv[:, 0] + num_walls) / (num_walls + 2) triangle_uvs.append(triangle_uv) # normalize to [0, 1] triangle_uv = (vertices_floor[:, :2] - vertices_floor_min) / (vertices_floor_max - vertices_floor_min) triangle_uv[:, 0] = (triangle_uv[:, 0] + num_walls + 1) / (num_walls + 2) triangle_uvs.append(triangle_uv) # 3. Merge wall, floor, and ceiling vertices.append(vertices_floor) vertices.append(vertices_floor + delta_height) vertices = np.concatenate(vertices, axis=0) triangles = np.concatenate(triangles, axis=0) textures.append(texture_floor) textures.append(texture_ceiling) textures = np.concatenate(textures, axis=1) triangle_uvs = np.concatenate(triangle_uvs, axis=0) mesh = open3d.geometry.TriangleMesh( vertices=open3d.utility.Vector3dVector(vertices), triangles=open3d.utility.Vector3iVector(triangles) ) mesh.compute_vertex_normals() mesh.texture = open3d.geometry.Image(textures) mesh.triangle_uvs = np.array(triangle_uvs[triangles.reshape(-1), :], dtype=np.float64) return mesh