LiangliangNan / Easy3D

A lightweight, easy-to-use, and efficient C++ library for processing and rendering 3D data
GNU General Public License v3.0
1.35k stars 243 forks source link

Can we highlight multiple faces? (Not entire model) #162

Closed KenKenhehe closed 1 year ago

KenKenhehe commented 1 year ago

I am trying to highlight multiple faces for debugging purposes, but it seems like we can only highlight 1 face at a time(highlighting a new face automatically cancel the highlighting the old face)?

I am using this code to do the highlighting: image "f" is a SurfaceMesh::Face structure

I find this this code here which seems to be the cause:

image

Is there any code we can use to prevent this behaviour? or do we need to implement this our self?

LiangliangNan commented 1 year ago

I assume you will be handling triangle meshes. Currently the triangles with indices within the range [min, max] will be highlighted. This means a set of consecutive faces can be highlighted.

A few ideas to implement what you need: 1) store the faces you want to hight in consecutively, and send the range of the face indices to the shader. 2) add a "f:color" attribute to the faces to indicate highlight or not. Easy3D can already render such color attributes. 3) add a boolean type attribute to the faces (false: not highligh, true: highlight). Then you have a scalar field and Easy3D can render it already. Among these ideas, 2) is the easiest to implement and maintain. 3) is the most efficient since every time the status is changed, only the boolean type of information needs to be updated to GPU.

Hope this helps.

KenKenhehe commented 1 year ago

For 2), how does it render color attribute? Is there a code example?

LiangliangNan commented 1 year ago

First, add a color attribute to the faces:

     // add a color property called "f:color"
     auto face_color = mesh->add_face_property<vec3>("f:color", default_color);  
     // use the color property for rendering
     faces_drawable->set_property_coloring(State::FACE, "f:color");   

Then change the color of your interested faces by

     face_color[f] = vec3(1, 0, 0); 

Every time when the color/selection has changed, update the new color to GPU and informs the viewer:

    mesh->renderer()->update();
    viewer_->update();
KenKenhehe commented 1 year ago

Thank you, this is helpful. I can implement this now, but would be good if you can also provide code example for 1)

LiangliangNan commented 1 year ago

Thank you, this is helpful. I can implement this now, but would be good if you can also provide code example for 1) The first option requires to sort the indices stored in the element array buffer in a way such that all your highlighted faces are stored consecutively. Below is an example:

Assume your indices are

std::vector<GLuint> indices
{
    0, 1, 3,
    0, 3, 2,  <---- a face you want to highlight
    5, 7, 3,
    0, 5, 1,  <---- another face you want to highlight
    1, 2, 4,
    2, 0, 6   <---- the third face you want to highlight
};

You can sort the indices as

std::vector<GLuint> indices
{
    0, 1, 3,
    0, 3, 2,  <---- a face you want to highlight  ---- index in the range is 1
    0, 5, 1,  <---- another face you want to highlight
    2, 0, 6   <---- the third face you want to highlight  ---- index in the range is 3
    5, 7, 3,
    1, 2, 4
};

And then indicate the range of face indices (all faces with an index within this range will be highlighted):

drawable->set_highlight_range({1, 3});