Mercurial > octave
diff libinterp/corefcn/gl-render.cc @ 25820:218feb083dcc
Use "facenormals" for flat lighting on patches (bug #54024).
* gl-render.cc (vertex_data): Store vertex normals and face normals.
* gl-render.cc (draw_patch): Use face normals if lighting mode is "flat".
author | Markus Mützel <markus.muetzel@gmx.de> |
---|---|
date | Tue, 21 Aug 2018 22:02:23 +0200 |
parents | b2917b7858ba |
children | 2c42ed37cfc2 |
line wrap: on
line diff
--- a/libinterp/corefcn/gl-render.cc Mon Aug 20 13:15:02 2018 -0700 +++ b/libinterp/corefcn/gl-render.cc Tue Aug 21 22:02:23 2018 +0200 @@ -365,7 +365,8 @@ public: Matrix coords; Matrix color; - Matrix normal; + Matrix vertex_normal; + Matrix face_normal; double alpha; float ambient; float diffuse; @@ -377,16 +378,16 @@ refcount<int> count; vertex_data_rep (void) - : coords (), color (), normal (), alpha (), + : coords (), color (), vertex_normal (), face_normal (), alpha (), ambient (), diffuse (), specular (), specular_exp (), specular_color_refl (), count (1) { } - vertex_data_rep (const Matrix& c, const Matrix& col, const Matrix& n, - double a, float as, float ds, float ss, float se, - float scr) - : coords (c), color (col), normal (n), alpha (a), - ambient (as), diffuse (ds), specular (ss), specular_exp (se), - specular_color_refl (scr), count (1) { } + vertex_data_rep (const Matrix& c, const Matrix& col, const Matrix& vn, + const Matrix& fn, double a, float as, float ds, float ss, + float se, float scr) + : coords (c), color (col), vertex_normal (vn), face_normal (fn), + alpha (a), ambient (as), diffuse (ds), specular (ss), + specular_exp (se), specular_color_refl (scr), count (1) { } }; private: @@ -406,10 +407,10 @@ vertex_data (const vertex_data& v) : rep (v.rep) { rep->count++; } - vertex_data (const Matrix& c, const Matrix& col, const Matrix& n, - double a, float as, float ds, float ss, float se, - float scr) - : rep (new vertex_data_rep (c, col, n, a, as, ds, ss, se, scr)) + vertex_data (const Matrix& c, const Matrix& col, const Matrix& vn, + const Matrix& fn, double a, float as, float ds, float ss, + float se, float scr) + : rep (new vertex_data_rep (c, col, vn, fn, a, as, ds, ss, se, scr)) { } vertex_data (vertex_data_rep *new_rep) @@ -506,8 +507,10 @@ } } - if (light_mode > 0 && (first || light_mode == GOURAUD)) - glNormal3dv (v->normal.data ()); + if (light_mode == FLAT && first) + glNormal3dv (v->face_normal.data ()); + else if (light_mode == GOURAUD) + glNormal3dv (v->vertex_normal.data ()); glVertex3dv (v->coords.data ()); @@ -531,7 +534,8 @@ Matrix vv (1, 3, 0.0); Matrix cc; - Matrix nn (1, 3, 0.0); + Matrix vnn (1, 3, 0.0); + Matrix fnn (1, 3, 0.0); double aa = 0.0; vv(0) = xyz[0]; @@ -546,18 +550,26 @@ cc(ic) += (w[iv] * v[iv]->color (ic)); } - if (v[0]->normal.numel () > 0) + if (v[0]->vertex_normal.numel () > 0) { for (int in = 0; in < 3; in++) for (int iv = 0; iv < vmax; iv++) - nn(in) += (w[iv] * v[iv]->normal (in)); + vnn(in) += (w[iv] * v[iv]->vertex_normal (in)); + } + + if (v[0]->face_normal.numel () > 0) + { + for (int in = 0; in < 3; in++) + for (int iv = 0; iv < vmax; iv++) + fnn(in) += (w[iv] * v[iv]->face_normal (in)); } for (int iv = 0; iv < vmax; iv++) aa += (w[iv] * v[iv]->alpha); - vertex_data new_v (vv, cc, nn, aa, v[0]->ambient, v[0]->diffuse, - v[0]->specular, v[0]->specular_exp, v[0]->specular_color_refl); + vertex_data new_v (vv, cc, vnn, fnn, aa, v[0]->ambient, v[0]->diffuse, + v[0]->specular, v[0]->specular_exp, + v[0]->specular_color_refl); tmp_vdata.push_back (new_v); *out_data = new_v.get_rep (); @@ -2942,7 +2954,6 @@ const Matrix f = props.get_faces ().matrix_value (); const Matrix v = xform.scale (props.get_vertices ().matrix_value ()); Matrix c; - const Matrix n = props.get_vertexnormals ().matrix_value (); Matrix a; double fa = 1.0; @@ -2953,8 +2964,6 @@ bool has_z = (v.columns () > 2); bool has_facecolor = false; bool has_facealpha = false; - // FIXME: remove when patch object has normal computation (patch #8951) - bool has_normals = (n.rows () == nv); int fc_mode = ((props.facecolor_is ("none") || props.facecolor_is_rgb () || draw_all) ? 0 : @@ -2983,6 +2992,11 @@ float se = props.get_specularexponent () * 5; // to fit Matlab float scr = props.get_specularcolorreflectance (); + const Matrix vn = props.get_vertexnormals ().matrix_value (); + bool has_vertex_normals = (vn.rows () == nv); + const Matrix fn = props.get_facenormals ().matrix_value (); + bool has_face_normals = (fn.rows () == nf); + boolMatrix clip (1, nv, false); if (has_z) @@ -3056,23 +3070,37 @@ Matrix vv (1, 3, 0.0); Matrix cc; - Matrix nn (1, 3, 0.0); + Matrix vnn (1, 3, 0.0); + Matrix fnn (1, 3, 0.0); double aa = 1.0; vv(0) = v(idx,0); vv(1) = v(idx,1); if (has_z) vv(2) = v(idx,2); - if (has_normals) + if (((fl_mode == FLAT) || (el_mode == FLAT)) && has_face_normals) { double dir = 1.0; if (bfl_mode > 0) - dir = ((n(idx,0) * view_vector(0) - + n(idx,1) * view_vector(1) - + n(idx,2) * view_vector(2) < 0) + dir = ((fn(i,0) * view_vector(0) + + fn(i,1) * view_vector(1) + + fn(i,2) * view_vector(2) < 0) ? ((bfl_mode > 1) ? 0.0 : -1.0) : 1.0); - nn(0) = dir * n(idx,0); - nn(1) = dir * n(idx,1); - nn(2) = dir * n(idx,2); + fnn(0) = dir * fn(i,0); + fnn(1) = dir * fn(i,1); + fnn(2) = dir * fn(i,2); + } + if (((fl_mode == GOURAUD) || (el_mode == GOURAUD)) && + has_vertex_normals) + { + double dir = 1.0; + if (bfl_mode > 0) + dir = ((vn(idx,0) * view_vector(0) + + vn(idx,1) * view_vector(1) + + vn(idx,2) * view_vector(2) < 0) + ? ((bfl_mode > 1) ? 0.0 : -1.0) : 1.0); + vnn(0) = dir * vn(idx,0); + vnn(1) = dir * vn(idx,1); + vnn(2) = dir * vn(idx,2); } if (c.numel () > 0) { @@ -3092,7 +3120,7 @@ aa = a(idx); } - vdata[i+j*fr] = vertex_data (vv, cc, nn, aa, as, ds, ss, se, scr); + vdata[i+j*fr] = vertex_data (vv, cc, vnn, fnn, aa, as, ds, ss, se, scr); } if (fl_mode > 0 || el_mode > 0) @@ -3126,7 +3154,7 @@ } } - if ((fl_mode > 0) && do_lighting && has_normals) + if ((fl_mode > 0) && do_lighting) glEnable (GL_LIGHTING); // NOTE: Push filled part of patch backwards to avoid Z-fighting @@ -3229,7 +3257,7 @@ it1++; } - if ((fl_mode > 0) && do_lighting && has_normals) + if ((fl_mode > 0) && do_lighting) glDisable (GL_LIGHTING); } else @@ -3265,7 +3293,7 @@ } } - if ((el_mode > 0) && do_lighting && has_normals) + if ((el_mode > 0) && do_lighting) glEnable (GL_LIGHTING); double linewidth = props.get_linewidth (); @@ -3368,7 +3396,7 @@ set_linestyle ("-"); // Disable LineStipple set_linewidth (0.5f); - if ((el_mode > 0) && do_lighting && has_normals) + if ((el_mode > 0) && do_lighting) glDisable (GL_LIGHTING); } else