Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions BGL/include/CGAL/draw_face_graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ void compute_elements(const FG &fg,

if (gs_options.are_faces_enabled())
{
// Colour by value: name the value once, for the legend.
if (!gs_options.face_value_name.empty())
{ graphics_scene.set_value_name(gs_options.face_value_name); }
for (auto fh : faces(fg))
{
if (fh != boost::graph_traits<FG>::null_face() && // face exists
Expand All @@ -78,6 +81,9 @@ void compute_elements(const FG &fg,
hd = next(hd, fg);
}
while (hd != first_hd);
// Colour by value: attach the face's scalar value before committing it.
if (gs_options.valued_face(fg, fh))
{ graphics_scene.set_face_value(gs_options.face_value(fg, fh)); }
graphics_scene.face_end();
}
}
Expand Down
12 changes: 12 additions & 0 deletions Basic_viewer/doc/Basic_viewer/Concepts/GraphicsSceneOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,18 @@ class GraphicsSceneOptions
/// `nullptr` by default.
std::function<CGAL::IO::Color(const DS &, face_descriptor)> face_color;

/// `std::function` that returns `true` if the given face carries a scalar value to
/// colour it by, `false` otherwise. `false` by default.
std::function<bool(const DS &, face_descriptor)> valued_face;

/// `std::function` that returns the scalar value of the given face. Used only when
/// `valued_face()` returns `true`. The viewer normalises the values over their range
/// and maps them to a color palette.
std::function<float(const DS &, face_descriptor)> face_value;

/// name of the value, shown in the viewer's color legend (for example "aspect ratio").
std::string face_value_name;

/// ignores all vertices when `b` is `true`; otherwise ignores only vertices for which `ignore_vertex()` returns `true`.
void ignore_all_vertices(bool b);

Expand Down
46 changes: 44 additions & 2 deletions Basic_viewer/include/CGAL/Basic_shaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,38 @@ uniform highp vec4 u_PointPlane;
uniform mediump float u_RenderingMode;
uniform mediump float u_RenderingTransparency;

// Colour by value: 0 keeps the vertex colour, otherwise a palette index. The
// value shown is the signed distance from the fragment to the clipping plane,
// normalised to [u_ValueMin, u_ValueMax].
uniform mediump float u_ColorMapMode;
uniform mediump float u_ValueMin;
uniform mediump float u_ValueMax;
// Per cell: the viewer gives one value for the whole cell (its centre distance or
// its size), so a whole cell takes one flat colour and neighbouring cells do not melt.
uniform int u_ColorPerCell;
uniform highp float u_CellValue;

vec3 colour_palette(float t, float mode)
{
if (mode < 1.5)
{ return clamp(vec3(t*3.0, t*3.0-1.0, t*3.0-2.0), 0.0, 1.0); } // heat
if (mode < 2.5)
{ return clamp(vec3(1.5-abs(4.0*t-3.0), 1.5-abs(4.0*t-2.0), 1.5-abs(4.0*t-1.0)),
0.0, 1.0); } // jet
if (mode < 3.5)
{ return vec3(t); } // grey ramp
// viridis, a perceptually uniform map (polynomial fit by Matt Zucker). The same
// coefficients are mirrored in the viewer's legend so the bar matches the faces.
const vec3 c0=vec3(0.2777273272234177, 0.005407344544966578, 0.3340998053353061);
const vec3 c1=vec3(0.1050930431085774, 1.404613529898575, 1.384590162594685);
const vec3 c2=vec3(-0.3308618287255563, 0.214847559468213, 0.09509516302823659);
const vec3 c3=vec3(-4.634230498983486, -5.799100973351585, -19.33244095627987);
const vec3 c4=vec3(6.228269936347081, 14.17993336680509, 56.69055260068105);
const vec3 c5=vec3(4.776384997670288, -13.74514537774601, -65.35303263337234);
const vec3 c6=vec3(-5.435455855934631, 4.645852612178535, 26.3124352495832);
return clamp(c0+t*(c1+t*(c2+t*(c3+t*(c4+t*(c5+t*c6))))), 0.0, 1.0);
}

void main(void)
{
highp vec3 L = u_LightPos.xyz - vs_fP.xyz;
Expand All @@ -84,9 +116,19 @@ void main(void)
L = normalize(L);
V = normalize(V);

// Base colour is the vertex colour, or a palette applied to the value.
vec3 base = fColor.rgb;
if (u_ColorMapMode > 0.5)
{
float value = (u_ColorPerCell != 0) ? u_CellValue
: dot(ls_fP.xyz-u_PointPlane.xyz, normalize(u_ClipPlane.xyz));
float t = clamp((value-u_ValueMin)/max(u_ValueMax-u_ValueMin, 1e-6), 0.0, 1.0);
base = colour_palette(t, u_ColorMapMode);
}

highp vec3 R = reflect(-L, a_Normal);
highp vec4 diffuse = vec4(max(dot(a_Normal,L), 0.0) * u_LightDiff.rgb * fColor.rgb, 1.0);
highp vec4 ambient = vec4(u_LightAmb.rgb * fColor.rgb, 1.0);
highp vec4 diffuse = vec4(max(dot(a_Normal,L), 0.0) * u_LightDiff.rgb * base, 1.0);
highp vec4 ambient = vec4(u_LightAmb.rgb * base, 1.0);
highp vec4 specular = pow(max(dot(R,V), 0.0), u_SpecPower) * u_LightSpec;

// onPlane == 1: inside clipping plane, should be solid;
Expand Down
42 changes: 42 additions & 0 deletions Basic_viewer/include/CGAL/Graphics_scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,13 @@ class Graphics_scene
return m_buffer_for_faces.is_a_face_started();
}

/// sets the scalar value of the face currently being built. The viewer can colour
/// the faces by these values, normalised over their range and mapped to a palette.
void set_face_value(float v) { m_current_face_value=v; m_has_face_values=true; }

/// sets the name of the value, shown in the viewer's colour legend.
void set_value_name(const std::string &n) { m_value_name=n; }

void face_begin()
{
if (a_face_started())
Expand Down Expand Up @@ -314,6 +321,7 @@ class Graphics_scene
const unsigned int idx=static_cast<unsigned int>(m_faces.size());
m_faces.emplace_back(m_current_face_start,
number_of_elements(POS_FACES)-m_current_face_start);
record_current_face_value();
m_face_dedup.emplace(std::move(key), idx);
m_volume_faces.back().push_back(idx);
return;
Expand All @@ -324,6 +332,22 @@ class Graphics_scene
// Record this face's vertex range in POS_FACES, for the clip-plane cap.
m_faces.emplace_back(m_current_face_start,
number_of_elements(POS_FACES) - m_current_face_start);
record_current_face_value();
}

// Colour by value: store the value of the face just committed, parallel to
// m_faces, and keep the min and max for the palette range.
void record_current_face_value()
{
if (m_has_face_values)
{
if (m_face_values.empty())
{ m_face_value_min=m_face_value_max=m_current_face_value; }
else
{ if (m_current_face_value<m_face_value_min) { m_face_value_min=m_current_face_value; }
if (m_current_face_value>m_face_value_max) { m_face_value_max=m_current_face_value; } }
}
m_face_values.push_back(m_current_face_value);
}

// Clip-plane cap: a volume groups the faces added until volume_end, de-duplicated
Expand Down Expand Up @@ -366,6 +390,14 @@ class Graphics_scene
const std::vector<CGAL::Bbox_3> &get_volume_bboxes() const
{ return m_volume_bboxes; }

// Colour by value: the per-face values set by the drawer, whether any were set,
// the legend name, and the value range.
const std::vector<float> &get_face_values() const { return m_face_values; }
bool has_face_values() const { return m_has_face_values; }
const std::string &value_name() const { return m_value_name; }
float face_value_min() const { return m_face_value_min; }
float face_value_max() const { return m_face_value_max; }

template <typename KPoint>
void add_text(const KPoint &kp, const std::string &txt)
{
Expand Down Expand Up @@ -509,6 +541,16 @@ class Graphics_scene
std::vector<CGAL::Bbox_3> m_volume_bboxes;
unsigned int m_current_face_start = 0;

// Colour by value: an optional scalar per face, set by the drawer, that the viewer
// maps to a palette (like the colour, but any float). Each value is parallel to
// m_faces; m_value_name labels the legend.
std::vector<float> m_face_values;
float m_current_face_value = 0.f;
bool m_has_face_values = false;
std::string m_value_name;
float m_face_value_min = 0.f;
float m_face_value_max = 1.f;

// Clip-plane cap: geometric face de-duplication during volume building. The key
// is the sorted face vertex positions, so both sides of a shared wall match.
// Hashed so the build stays linear on meshes with many faces.
Expand Down
15 changes: 15 additions & 0 deletions Basic_viewer/include/CGAL/Graphics_scene_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ struct Graphics_scene_options<DS, VertexDescriptor, EdgeDescriptor, FaceDescript
colored_face=[](const DS &, face_descriptor)->bool { return false; };

face_wireframe=[](const DS &, face_descriptor)->bool { return false; };

valued_face=[](const DS &, face_descriptor)->bool { return false; };
}

// The seven following functions should not be null
Expand All @@ -65,6 +67,19 @@ struct Graphics_scene_options<DS, VertexDescriptor, EdgeDescriptor, FaceDescript

std::function<bool(const DS &, face_descriptor)> face_wireframe;

/// `std::function` that returns `true` if the given face carries a scalar value to
/// colour it by, `false` otherwise. `false` by default.
std::function<bool(const DS &, face_descriptor)> valued_face;

/// `std::function` that returns the scalar value of the given face. Called only
/// when `valued_face()` returns `true`. The viewer normalises the values over their
/// range and maps them to a colour palette.
std::function<float(const DS &, face_descriptor)> face_value;

/// The name of the value, shown in the viewer's colour legend (for example
/// "aspect ratio"). Empty by default.
std::string face_value_name;

// These functions must be non null if the corresponding colored_XXX function
// returns true.
std::function<CGAL::IO::Color(const DS &, vertex_descriptor)> vertex_color;
Expand Down
Loading
Loading