/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t gb_tessellator_mesh_make(gb_tessellator_impl_t* impl, gb_polygon_ref_t polygon) { // check tb_assert(impl && polygon); // the points gb_point_ref_t points = polygon->points; tb_uint16_t const* counts = polygon->counts; tb_assert_and_check_return_val(points && counts, tb_false); // not exists mesh? if (!impl->mesh) { // init func tb_element_t edge_element = tb_element_mem(sizeof(gb_tessellator_edge_t), tb_null, tb_null); tb_element_t face_element = tb_element_mem(sizeof(gb_tessellator_face_t), tb_null, tb_null); tb_element_t vertex_element = tb_element_mem(sizeof(gb_tessellator_vertex_t), tb_null, tb_null); #ifdef __gb_debug__ // init func cstr for gb_mesh_dump edge_element.cstr = gb_tessellator_edge_cstr; face_element.cstr = gb_tessellator_face_cstr; vertex_element.cstr = gb_tessellator_vertex_cstr; #endif // init mesh impl->mesh = gb_mesh_init(edge_element, face_element, vertex_element); /* init the order * * the new edges/faces/vertice will be inserted to the head of list */ gb_mesh_edge_order_set(impl->mesh, GB_MESH_ORDER_INSERT_HEAD); gb_mesh_face_order_set(impl->mesh, GB_MESH_ORDER_INSERT_HEAD); gb_mesh_vertex_order_set(impl->mesh, GB_MESH_ORDER_INSERT_HEAD); // init listener gb_mesh_listener_set(impl->mesh, gb_tessellator_listener, impl->mesh); gb_mesh_listener_event_add(impl->mesh, GB_MESH_EVENT_FACE_SPLIT | GB_MESH_EVENT_EDGE_SPLIT); } // check gb_mesh_ref_t mesh = impl->mesh; tb_assert_and_check_return_val(mesh, tb_false); // clear mesh first gb_mesh_clear(mesh); // done gb_point_ref_t point = tb_null; tb_uint16_t count = *counts++; tb_size_t index = 0; gb_mesh_edge_ref_t edge = tb_null; gb_mesh_edge_ref_t edge_first = tb_null; while (index < count) { // the point point = points++; // first point? if (!index) { // must be closed contour tb_assertf(gb_point_eq(point, point + count - 1), "this contour(%lu: %{point} => %{point}) is not closed!", count, point, point + count - 1); // clear the edge edge = tb_null; // clear the first edge edge_first = tb_null; // trace tb_trace_d("move_to: %{point}", point); } // closed? else if (index + 1 == count) { // trace tb_trace_d("closed: %{point}", point); // connect an edge to the first edge edge = gb_mesh_edge_connect(mesh, edge, edge_first); // init edge.faces.inside gb_tessellator_face_inside_set(gb_mesh_edge_lface(edge), 0); gb_tessellator_face_inside_set(gb_mesh_edge_rface(edge), 0); } else { // trace tb_trace_d("line_to: %{point}", point); // exists the first edge? if (edge_first) { // append an edge edge = gb_mesh_edge_append(mesh, edge); } else { // make a new non-loop edge edge = gb_mesh_edge_make(mesh); // save the first edge edge_first = edge; } } // has new edge? if (edge) { // init edge.winding gb_tessellator_edge_winding_set(edge, 1); gb_tessellator_edge_winding_set(gb_mesh_edge_sym(edge), -1); // init edge.region gb_tessellator_edge_region_set(edge, tb_null); gb_tessellator_edge_region_set(gb_mesh_edge_sym(edge), tb_null); // init edge.dst gb_tessellator_vertex_point_set(gb_mesh_edge_dst(edge), point); } // next point index++; // next polygon if (index == count) { // next count = *counts++; index = 0; } } #ifdef __gb_debug__ // check mesh gb_mesh_check(mesh); #endif // ok? return !gb_mesh_is_empty(mesh); }
static tb_void_t gb_demo_utils_mesh_radiation() { // trace tb_trace_i("=========================================================================="); // init mesh gb_mesh_ref_t mesh = gb_mesh_init(tb_element_str(tb_true), tb_element_str(tb_true), tb_element_str(tb_true)); if (mesh) { // init listener gb_mesh_listener_set(mesh, gb_demo_utils_mesh_listener, mesh); gb_mesh_listener_event_add(mesh, GB_MESH_EVENT_FACE_MERGE | GB_MESH_EVENT_FACE_SPLIT | GB_MESH_EVENT_EDGE_MERGE | GB_MESH_EVENT_EDGE_SPLIT); // make a edge gb_mesh_edge_ref_t edge1 = gb_mesh_edge_make(mesh); if (edge1) { // the face gb_mesh_face_ref_t face = gb_mesh_edge_lface(edge1); tb_assert_abort(face == gb_mesh_edge_rface(edge1)); // save face name gb_mesh_face_data_set(mesh, face, "face"); /* make a radiation * * v4 * / \ * | * | * | e4 * | * | * | * <---------------- v0 ----------------> * v1 e1 | e3 v3 * | * | * | e2 * | * | * \ / * v2 */ gb_mesh_edge_ref_t edge2 = gb_mesh_edge_append(mesh, gb_mesh_edge_sym(edge1)); gb_mesh_edge_ref_t edge3 = gb_mesh_edge_append(mesh, gb_mesh_edge_sym(edge1)); gb_mesh_edge_ref_t edge4 = gb_mesh_edge_append(mesh, gb_mesh_edge_sym(edge1)); // save edge name gb_mesh_edge_data_set(mesh, edge1, "e1"); gb_mesh_edge_data_set(mesh, edge2, "e2"); gb_mesh_edge_data_set(mesh, edge3, "e3"); gb_mesh_edge_data_set(mesh, edge4, "e4"); // save vertex name gb_mesh_vertex_data_set(mesh, gb_mesh_edge_org(edge1), "v0"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge1), "v1"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge2), "v2"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge3), "v3"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge4), "v4"); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("radiation: make"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif /* remove one * * v4 * / \ * | * | * | e4 * | * | * | * v0 ----------------> * | e3 v3 * | * | * | e2 * | * | * \ / * v2 */ gb_mesh_edge_remove(mesh, edge1); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("radiation: kill"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif // remove all gb_mesh_edge_remove(mesh, edge2); gb_mesh_edge_remove(mesh, edge3); gb_mesh_edge_remove(mesh, edge4); // check tb_assert_abort(gb_mesh_is_empty(mesh)); } // exit mesh gb_mesh_exit(mesh); } }