Esempio n. 1
0
File: mesh.c Progetto: waruqi/gbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * 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);
}
Esempio n. 2
0
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);
    }
}