GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
gl-render.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2008-2017 Michael Goffioul
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <iostream>
28 
29 #if defined (HAVE_WINDOWS_H)
30 # define WIN32_LEAN_AND_MEAN
31 # include <windows.h>
32 #endif
33 
34 #include <lo-mappers.h>
35 #include "oct-locbuf.h"
36 #include "oct-refcount.h"
37 
38 #include "errwarn.h"
39 #include "gl-render.h"
40 #include "oct-opengl.h"
41 #include "text-renderer.h"
42 
43 #if defined (HAVE_OPENGL)
44 
45 static int
47 {
48  int m = 1;
49 
50  while (m < n && m < std::numeric_limits<int>::max ())
51  m <<= 1;
52 
53  return m;
54 }
55 
56 #endif
57 
58 namespace octave
59 {
60 #if defined (HAVE_OPENGL)
61 
62 #define LIGHT_MODE GL_FRONT_AND_BACK
63 
64  // Use symbolic names for axes
65  enum
66  {
70  };
71 
72  // Use symbolic names for color mode
73  enum
74  {
79  };
80 
81  // Use symbolic names for lighting
82  enum
83  {
85  //FLAT, // Already declared in anonymous enum for color mode
86  GOURAUD = 2
87  };
88 
89  // Win32 API requires the CALLBACK attributes for
90  // GLU callback functions. Define it to empty on
91  // other platforms.
92 #if ! defined (CALLBACK)
93 # define CALLBACK
94 #endif
95 
96  class
98  {
99  protected:
101  {
102  public:
103  texture_rep (void)
104  : id (), w (), h (), tw (), th (), tx (), ty (),
105  valid (false), count (1)
106  { }
107 
108  texture_rep (GLuint id_arg, int w_arg, int h_arg, int tw_arg, int th_arg)
109  : id (id_arg), w (w_arg), h (h_arg), tw (tw_arg), th (th_arg),
110  tx (double(w)/tw), ty (double(h)/th), valid (true),
111  count (1) { }
112 
114  {
115  if (valid)
116  glDeleteTextures (1, &id);
117  }
118 
119  void bind (int mode) const
120  { if (valid) glBindTexture (mode, id); }
121 
122  void tex_coord (double q, double r) const
123  { if (valid) glTexCoord2d (q*tx, r*ty); }
124 
125  GLuint id;
126  int w, h;
127  int tw, th;
128  double tx, ty;
129  bool valid;
131  };
132 
134 
135  private:
136  opengl_texture (texture_rep *_rep) : rep (_rep) { }
137 
138  public:
139  opengl_texture (void) : rep (new texture_rep ()) { }
140 
142  : rep (tx.rep)
143  {
144  rep->count++;
145  }
146 
148  {
149  if (--rep->count == 0)
150  delete rep;
151  }
152 
153  opengl_texture& operator = (const opengl_texture& tx)
154  {
155  if (--rep->count == 0)
156  delete rep;
157 
158  rep = tx.rep;
159  rep->count++;
160 
161  return *this;
162  }
163 
164  static opengl_texture create (const octave_value& data);
165 
166  void bind (int mode = GL_TEXTURE_2D) const
167  { rep->bind (mode); }
168 
169  void tex_coord (double q, double r) const
170  { rep->tex_coord (q, r); }
171 
172  bool is_valid (void) const
173  { return rep->valid; }
174  };
175 
176  opengl_texture
178  {
180 
181  dim_vector dv (data.dims ());
182 
183  // Expect RGB data
184  if (dv.ndims () == 3 && dv(2) == 3)
185  {
186  // FIXME: dim_vectors hold octave_idx_type values.
187  // Should we check for dimensions larger than intmax?
188  int h, w, tw, th;
189  h = dv(0), w = dv(1);
190  GLuint id;
191  bool ok = true;
192 
193  tw = next_power_of_2 (w);
194  th = next_power_of_2 (h);
195 
196  glGenTextures (1, &id);
197  glBindTexture (GL_TEXTURE_2D, id);
198 
199  if (data.is_double_type ())
200  {
201  const NDArray xdata = data.array_value ();
202 
203  OCTAVE_LOCAL_BUFFER (float, a, (3*tw*th));
204 
205  for (int i = 0; i < h; i++)
206  {
207  for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3)
208  {
209  a[idx] = xdata(i,j,0);
210  a[idx+1] = xdata(i,j,1);
211  a[idx+2] = xdata(i,j,2);
212  }
213  }
214 
215  glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, GL_RGB, GL_FLOAT, a);
216  }
217  else if (data.is_uint8_type ())
218  {
219  const uint8NDArray xdata = data.uint8_array_value ();
220 
221  OCTAVE_LOCAL_BUFFER (octave_uint8, a, (3*tw*th));
222 
223  for (int i = 0; i < h; i++)
224  {
225  for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3)
226  {
227  a[idx] = xdata(i,j,0);
228  a[idx+1] = xdata(i,j,1);
229  a[idx+2] = xdata(i,j,2);
230  }
231  }
232 
233  glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0,
234  GL_RGB, GL_UNSIGNED_BYTE, a);
235  }
236  else
237  {
238  ok = false;
239  warning ("opengl_texture::create: invalid texture data type (double or uint8 required)");
240  }
241 
242  if (ok)
243  {
244  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
245  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
246 
247  if (glGetError () != GL_NO_ERROR)
248  warning ("opengl_texture::create: OpenGL error while generating texture data");
249  else
250  retval = opengl_texture (new texture_rep (id, w, h, tw, th));
251  }
252  }
253  else
254  warning ("opengl_texture::create: invalid texture data size");
255 
256  return retval;
257  }
258 
259  class
261  {
262  public:
263 #if defined (HAVE_FRAMEWORK_OPENGL) && defined (HAVE_GLUTESSCALLBACK_THREEDOTS)
264  typedef GLvoid (CALLBACK *fcn) (...);
265 #else
266  typedef void (CALLBACK *fcn) (void);
267 #endif
268 
269  public:
270 
271  opengl_tesselator (void) : glu_tess (0), fill () { init (); }
272 
273  virtual ~opengl_tesselator (void)
274  { if (glu_tess) gluDeleteTess (glu_tess); }
275 
276  void begin_polygon (bool filled = true)
277  {
278  gluTessProperty (glu_tess, GLU_TESS_BOUNDARY_ONLY,
279  (filled ? GL_FALSE : GL_TRUE));
280  fill = filled;
281  gluTessBeginPolygon (glu_tess, this);
282  }
283 
284  void end_polygon (void) const
285  { gluTessEndPolygon (glu_tess); }
286 
287  void begin_contour (void) const
288  { gluTessBeginContour (glu_tess); }
289 
290  void end_contour (void) const
291  { gluTessEndContour (glu_tess); }
292 
293  void add_vertex (double *loc, void *data) const
294  { gluTessVertex (glu_tess, loc, data); }
295 
296  protected:
297  virtual void begin (GLenum /*type*/) { }
298 
299  virtual void end (void) { }
300 
301  virtual void vertex (void * /*data*/) { }
302 
303  virtual void combine (GLdouble [3] /*c*/, void * [4] /*data*/,
304  GLfloat [4] /*w*/, void ** /*out_data*/) { }
305 
306  virtual void edge_flag (GLboolean /*flag*/) { }
307 
308  virtual void error (GLenum err)
309  { ::error ("OpenGL tesselation error (%d)", err); }
310 
311  virtual void init (void)
312  {
313  glu_tess = gluNewTess ();
314 
315  gluTessCallback (glu_tess, GLU_TESS_BEGIN_DATA,
316  reinterpret_cast<fcn> (tess_begin));
317  gluTessCallback (glu_tess, GLU_TESS_END_DATA,
318  reinterpret_cast<fcn> (tess_end));
319  gluTessCallback (glu_tess, GLU_TESS_VERTEX_DATA,
320  reinterpret_cast<fcn> (tess_vertex));
321  gluTessCallback (glu_tess, GLU_TESS_COMBINE_DATA,
322  reinterpret_cast<fcn> (tess_combine));
323  gluTessCallback (glu_tess, GLU_TESS_EDGE_FLAG_DATA,
324  reinterpret_cast<fcn> (tess_edge_flag));
325  gluTessCallback (glu_tess, GLU_TESS_ERROR_DATA,
326  reinterpret_cast<fcn> (tess_error));
327  }
328 
329  bool is_filled (void) const { return fill; }
330 
331  private:
332  static void CALLBACK tess_begin (GLenum type, void *t)
333  { reinterpret_cast<opengl_tesselator *> (t)->begin (type); }
334 
335  static void CALLBACK tess_end (void *t)
336  { reinterpret_cast<opengl_tesselator *> (t)->end (); }
337 
338  static void CALLBACK tess_vertex (void *v, void *t)
339  { reinterpret_cast<opengl_tesselator *> (t)->vertex (v); }
340 
341  static void CALLBACK tess_combine (GLdouble c[3], void *v[4], GLfloat w[4],
342  void **out, void *t)
343  { reinterpret_cast<opengl_tesselator *> (t)->combine (c, v, w, out); }
344 
345  static void CALLBACK tess_edge_flag (GLboolean flag, void *t)
346  { reinterpret_cast<opengl_tesselator *> (t)->edge_flag (flag); }
347 
348  static void CALLBACK tess_error (GLenum err, void *t)
349  { reinterpret_cast<opengl_tesselator *> (t)->error (err); }
350 
351  private:
352 
353  // No copying!
354 
356 
357  opengl_tesselator operator = (const opengl_tesselator&);
358 
359  GLUtesselator *glu_tess;
360  bool fill;
361  };
362 
363  class
365  {
366  public:
368  {
369  public:
373  double alpha;
374  float ambient;
375  float diffuse;
376  float specular;
379 
380  // reference counter
382 
384  : coords (), color (), normal (), alpha (),
385  ambient (), diffuse (), specular (), specular_exp (),
386  specular_color_refl (), count (1) { }
387 
388  vertex_data_rep (const Matrix& c, const Matrix& col, const Matrix& n,
389  double a, float as, float ds, float ss, float se,
390  float scr)
391  : coords (c), color (col), normal (n), alpha (a),
392  ambient (as), diffuse (ds), specular (ss), specular_exp (se),
393  specular_color_refl (scr), count (1) { }
394  };
395 
396  private:
398 
399  vertex_data_rep *nil_rep (void) const
400  {
401  static vertex_data_rep *nr = new vertex_data_rep ();
402 
403  return nr;
404  }
405 
406  public:
407  vertex_data (void) : rep (nil_rep ())
408  { rep->count++; }
409 
410  vertex_data (const vertex_data& v) : rep (v.rep)
411  { rep->count++; }
412 
413  vertex_data (const Matrix& c, const Matrix& col, const Matrix& n,
414  double a, float as, float ds, float ss, float se,
415  float scr)
416  : rep (new vertex_data_rep (c, col, n, a, as, ds, ss, se, scr))
417  { }
418 
420  : rep (new_rep) { }
421 
423  {
424  if (--rep->count == 0)
425  delete rep;
426  }
427 
428  vertex_data& operator = (const vertex_data& v)
429  {
430  if (--rep->count == 0)
431  delete rep;
432 
433  rep = v.rep;
434  rep->count++;
435 
436  return *this;
437  }
438 
439  vertex_data_rep *get_rep (void) const { return rep; }
440  };
441 
442  class
444  {
445  public:
446  patch_tesselator (opengl_renderer *r, int cmode, int lmode, float idx = 0.0)
447  : opengl_tesselator (), renderer (r),
448  color_mode (cmode), light_mode (lmode), index (idx),
449  first (true), tmp_vdata ()
450  { }
451 
452  protected:
453  void begin (GLenum type)
454  {
455  //printf ("patch_tesselator::begin (%d)\n", type);
456  first = true;
457 
458  if (color_mode == INTERP || light_mode == GOURAUD)
459  glShadeModel (GL_SMOOTH);
460  else
461  glShadeModel (GL_FLAT);
462 
463  if (is_filled ())
464  renderer->set_polygon_offset (true, index);
465 
466  glBegin (type);
467  }
468 
469  void end (void)
470  {
471  //printf ("patch_tesselator::end\n");
472  glEnd ();
473  renderer->set_polygon_offset (false);
474  }
475 
476  void vertex (void *data)
477  {
479  = reinterpret_cast<vertex_data::vertex_data_rep *> (data);
480  //printf ("patch_tesselator::vertex (%g, %g, %g)\n", v->coords(0), v->coords(1), v->coords(2));
481 
482  // NOTE: OpenGL can re-order vertices. For "flat" coloring of FaceColor
483  // the first vertex must be identified in the draw_patch routine.
484 
485  if (color_mode == INTERP || (color_mode == FLAT && ! is_filled ()))
486  {
487  Matrix col = v->color;
488 
489  if (col.numel () == 3)
490  {
491  glColor3dv (col.data ());
492  if (light_mode > 0)
493  {
494  float buf[4] = { 0, 0, 0, 1 };
495 
496  for (int k = 0; k < 3; k++)
497  buf[k] = (v->ambient * col(k));
498  glMaterialfv (LIGHT_MODE, GL_AMBIENT, buf);
499 
500  for (int k = 0; k < 3; k++)
501  buf[k] = (v->diffuse * col(k));
502  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, buf);
503 
504  for (int k = 0; k < 3; k++)
505  buf[k] = v->specular * (v->specular_color_refl +
506  (1 - v->specular_color_refl) * col(k));
507  glMaterialfv (LIGHT_MODE, GL_SPECULAR, buf);
508 
509  }
510  }
511  }
512 
513  if (light_mode > 0 && (first || light_mode == GOURAUD))
514  glNormal3dv (v->normal.data ());
515 
516  glVertex3dv (v->coords.data ());
517 
518  first = false;
519  }
520 
521  void combine (GLdouble xyz[3], void *data[4], GLfloat w[4], void **out_data)
522  {
523  //printf ("patch_tesselator::combine\n");
524 
526  int vmax = 4;
527 
528  for (int i = 0; i < 4; i++)
529  {
530  v[i] = reinterpret_cast<vertex_data::vertex_data_rep *> (data[i]);
531 
532  if (vmax == 4 && ! v[i])
533  vmax = i;
534  }
535 
536  Matrix vv (1, 3, 0.0);
537  Matrix cc;
538  Matrix nn (1, 3, 0.0);
539  double aa = 0.0;
540 
541  vv(0) = xyz[0];
542  vv(1) = xyz[1];
543  vv(2) = xyz[2];
544 
545  if (v[0]->color.numel ())
546  {
547  cc.resize (1, 3, 0.0);
548  for (int ic = 0; ic < 3; ic++)
549  for (int iv = 0; iv < vmax; iv++)
550  cc(ic) += (w[iv] * v[iv]->color (ic));
551  }
552 
553  if (v[0]->normal.numel () > 0)
554  {
555  for (int in = 0; in < 3; in++)
556  for (int iv = 0; iv < vmax; iv++)
557  nn(in) += (w[iv] * v[iv]->normal (in));
558  }
559 
560  for (int iv = 0; iv < vmax; iv++)
561  aa += (w[iv] * v[iv]->alpha);
562 
563  vertex_data new_v (vv, cc, nn, aa, v[0]->ambient, v[0]->diffuse,
564  v[0]->specular, v[0]->specular_exp, v[0]->specular_color_refl);
565  tmp_vdata.push_back (new_v);
566 
567  *out_data = new_v.get_rep ();
568  }
569 
570  private:
571 
572  // No copying!
573 
575 
576  patch_tesselator& operator = (const patch_tesselator&);
577 
581  int index;
582  bool first;
583  std::list<vertex_data> tmp_vdata;
584  };
585 
586 #else
587 
588  class
590  {
591  // Dummy class.
592  };
593 
594 #endif
595 
596 }
597 
598 #if defined (HAVE_OPENGL)
599 
600 static int
602 {
603 
604  static int max_lights = 0;
605 
606  // Check actual maximum number of lights possible
607  if (max_lights == 0)
608  {
609  for (max_lights = 0; max_lights < GL_MAX_LIGHTS; max_lights++)
610  {
611  glDisable (GL_LIGHT0 + max_lights);
612  if (glGetError ())
613  break;
614  }
615  }
616 
617  return max_lights;
618 
619 }
620 
621 #endif
622 
623 namespace octave
624 {
626  : toolkit (), xform (), xmin (), xmax (), ymin (), ymax (),
627  zmin (), zmax (), xZ1 (), xZ2 (), marker_id (), filled_marker_id (),
628  camera_pos (), camera_dir (), interpreter ("none"), txt_renderer ()
629  {
630  // This constructor will fail if we don't have OpenGL or if the data
631  // types we assumed in our public interface aren't compatible with the
632  // OpenGL types.
633 
634 #if defined (HAVE_OPENGL)
635 
636  // Ensure that we can't request an image larger than OpenGL can handle.
637  // FIXME: should we check signed vs. unsigned?
638 
639  static bool ok = (sizeof (int) <= sizeof (GLsizei));
640 
641  if (! ok)
642  error ("the size of GLsizei is smaller than the size of int");
643 
644 #else
645 
646  err_disabled_feature ("opengl_renderer", "OpenGL");
647 
648 #endif
649  }
650 
651  void
652  opengl_renderer::draw (const graphics_object& go, bool toplevel)
653  {
654  if (! go.valid_object ())
655  return;
656 
657  const base_properties& props = go.get_properties ();
658 
659  if (! toolkit)
660  toolkit = props.get_toolkit ();
661 
662  if (go.isa ("figure"))
663  draw_figure (dynamic_cast<const figure::properties&> (props));
664  else if (go.isa ("axes"))
665  draw_axes (dynamic_cast<const axes::properties&> (props));
666  else if (go.isa ("line"))
667  draw_line (dynamic_cast<const line::properties&> (props));
668  else if (go.isa ("surface"))
669  draw_surface (dynamic_cast<const surface::properties&> (props));
670  else if (go.isa ("patch"))
671  draw_patch (dynamic_cast<const patch::properties&> (props));
672  else if (go.isa ("light"))
673  draw_light (dynamic_cast<const light::properties&> (props));
674  else if (go.isa ("hggroup"))
675  draw_hggroup (dynamic_cast<const hggroup::properties&> (props));
676  else if (go.isa ("text"))
677  draw_text (dynamic_cast<const text::properties&> (props));
678  else if (go.isa ("image"))
679  draw_image (dynamic_cast<const image::properties&> (props));
680  else if (go.isa ("uimenu") || go.isa ("uicontrol")
681  || go.isa ("uicontextmenu") || go.isa ("uitoolbar")
682  || go.isa ("uipushtool") || go.isa ("uitoggletool"))
683  ; // SKIP
684  else if (go.isa ("uipanel"))
685  {
686  if (toplevel)
687  draw_uipanel (dynamic_cast<const uipanel::properties&> (props), go);
688  }
689  else if (go.isa ("uibuttongroup"))
690  {
691  if (toplevel)
692  draw_uibuttongroup (dynamic_cast<const uibuttongroup::properties&> (props), go);
693  }
694  else
695  {
696  warning ("opengl_renderer: cannot render object of type '%s'",
697  props.graphics_object_name ().c_str ());
698  }
699 
700 #if defined (HAVE_OPENGL)
701 
702  GLenum gl_error = glGetError ();
703  if (gl_error)
704  warning ("opengl_renderer: Error %d occurred drawing '%s' object",
705  gl_error, props.graphics_object_name ().c_str ());
706 
707 #endif
708  }
709 
710 #if defined (HAVE_OPENGL)
711 
712  static std::string
713  gl_get_string (GLenum id)
714  {
715  // This is kind of ugly, but glGetString returns a pointer to GLubyte
716  // and there is no std::string constructor that matches. Is there a
717  // better way?
718 
719  std::ostringstream buf;
720  buf << glGetString (id);
721  return std::string (buf.str ());
722  }
723 
724 #endif
725 
726  void
728  {
729  // Initialize OpenGL context
730 
732 
733 #if defined (HAVE_OPENGL)
734 
735  props.set___gl_extensions__ (gl_get_string (GL_EXTENSIONS));
736  props.set___gl_renderer__ (gl_get_string (GL_RENDERER));
737  props.set___gl_vendor__ (gl_get_string (GL_VENDOR));
738  props.set___gl_version__ (gl_get_string (GL_VERSION));
739 
740 #endif
741 
742  // Draw children
743 
744  draw (props.get_all_children (), false);
745  }
746 
747  void
749  const graphics_object& go)
750  {
751  graphics_object fig = go.get_ancestor ("figure");
752  const figure::properties& figProps =
753  dynamic_cast<const figure::properties&> (fig.get_properties ());
754 
755  // Initialize OpenGL context
756 
758  props.get_backgroundcolor_rgb ());
759 
760  // Draw children
761 
762  draw (props.get_all_children (), false);
763  }
764 
765  void
767  const graphics_object& go)
768  {
769  graphics_object fig = go.get_ancestor ("figure");
770  const figure::properties& figProps =
771  dynamic_cast<const figure::properties&> (fig.get_properties ());
772 
773  // Initialize OpenGL context
774 
776  props.get_backgroundcolor_rgb ());
777 
778  // Draw children
779 
780  draw (props.get_all_children (), false);
781  }
782 
783  void
784  opengl_renderer::init_gl_context (bool enhanced, const Matrix& c)
785  {
786 #if defined (HAVE_OPENGL)
787 
788  // Initialize OpenGL context
789 
790  glEnable (GL_DEPTH_TEST);
791  glDepthFunc (GL_LEQUAL);
792  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
793  glAlphaFunc (GL_GREATER, 0.0f);
794  glEnable (GL_NORMALIZE);
795 
796  if (enhanced)
797  {
798  glEnable (GL_BLEND);
799  glEnable (GL_MULTISAMPLE);
800  bool has_multisample = false;
801  if (! glGetError ())
802  {
803  GLint iMultiSample, iNumSamples;
804  glGetIntegerv (GL_SAMPLE_BUFFERS, &iMultiSample);
805  glGetIntegerv (GL_SAMPLES, &iNumSamples);
806  if (iMultiSample == GL_TRUE && iNumSamples > 0)
807  has_multisample = true;
808  }
809 
810  if (! has_multisample)
811  {
812  // MultiSample not implemented. Use old-style anti-aliasing
813  glDisable (GL_MULTISAMPLE);
814  // Disabling GL_MULTISAMPLE will raise a gl error if it is not
815  // implemented. Thus, call glGetError to reset the error state.
816  glGetError ();
817 
818  glEnable (GL_LINE_SMOOTH);
819  glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
820  }
821  }
822  else
823  {
824  glDisable (GL_BLEND);
825  glDisable (GL_LINE_SMOOTH);
826  }
827 
828  // Clear background
829 
830  if (c.numel () >= 3)
831  {
832  glClearColor (c(0), c(1), c(2), 1);
833  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
834  }
835 
836  GLenum gl_error = glGetError ();
837  if (gl_error)
838  warning ("opengl_renderer: Error %d occurred in init_gl_context",
839  gl_error);
840 
841 #else
842 
843  octave_unused_parameter (enhanced);
844  octave_unused_parameter (c);
845 
846  // This shouldn't happen because construction of opengl_renderer
847  // objects is supposed to be impossible if OpenGL is not available.
848 
849  panic_impossible ();
850 
851 #endif
852  }
853 
854  void
855  opengl_renderer::render_grid (const double linewidth,
856  const std::string& gridstyle,
857  const Matrix& gridcolor, const double gridalpha,
858  const Matrix& ticks, double lim1, double lim2,
859  double p1, double p1N, double p2, double p2N,
860  int xyz, bool is_3D)
861  {
862 #if defined (HAVE_OPENGL)
863 
864  glColor4d (gridcolor(0), gridcolor(1), gridcolor(2), gridalpha);
865  set_linestyle (gridstyle, true, linewidth);
866  glBegin (GL_LINES);
867  for (int i = 0; i < ticks.numel (); i++)
868  {
869  double val = ticks(i);
870  if (lim1 <= val && val <= lim2)
871  {
872  if (xyz == X_AXIS)
873  {
874  glVertex3d (val, p1N, p2);
875  glVertex3d (val, p1, p2);
876  if (is_3D)
877  {
878  glVertex3d (val, p1, p2N);
879  glVertex3d (val, p1, p2);
880  }
881  }
882  else if (xyz == Y_AXIS)
883  {
884  glVertex3d (p1N, val, p2);
885  glVertex3d (p1, val, p2);
886  if (is_3D)
887  {
888  glVertex3d (p1, val, p2N);
889  glVertex3d (p1, val, p2);
890  }
891  }
892  else if (xyz == Z_AXIS)
893  {
894  glVertex3d (p1N, p2, val);
895  glVertex3d (p1, p2, val);
896  glVertex3d (p1, p2N, val);
897  glVertex3d (p1, p2, val);
898  }
899  }
900  }
901  glEnd ();
902  set_linestyle ("-"); // Disable LineStipple
903  double black[3] = {0, 0, 0};
904  glColor3dv (black);
905 
906 #else
907 
908  octave_unused_parameter (linewidth);
909  octave_unused_parameter (gridstyle);
910  octave_unused_parameter (gridcolor);
911  octave_unused_parameter (gridalpha);
912  octave_unused_parameter (ticks);
913  octave_unused_parameter (lim1);
914  octave_unused_parameter (lim2);
915  octave_unused_parameter (p1);
916  octave_unused_parameter (p1N);
917  octave_unused_parameter (p2);
918  octave_unused_parameter (p2N);
919  octave_unused_parameter (xyz);
920  octave_unused_parameter (is_3D);
921 
922  // This shouldn't happen because construction of opengl_renderer
923  // objects is supposed to be impossible if OpenGL is not available.
924 
925  panic_impossible ();
926 
927 #endif
928  }
929 
930  void
932  double lim1, double lim2,
933  double p1, double p1N,
934  double p2, double p2N,
935  double dx, double dy, double dz,
936  int xyz, bool mirror)
937  {
938 #if defined (HAVE_OPENGL)
939 
940  glBegin (GL_LINES);
941 
942  for (int i = 0; i < ticks.numel (); i++)
943  {
944  double val = ticks(i);
945 
946  if (lim1 <= val && val <= lim2)
947  {
948  if (xyz == X_AXIS)
949  {
950  glVertex3d (val, p1, p2);
951  glVertex3d (val, p1+dy, p2+dz);
952  if (mirror)
953  {
954  glVertex3d (val, p1N, p2N);
955  glVertex3d (val, p1N-dy, p2N-dz);
956  }
957  }
958  else if (xyz == Y_AXIS)
959  {
960  glVertex3d (p1, val, p2);
961  glVertex3d (p1+dx, val, p2+dz);
962  if (mirror)
963  {
964  glVertex3d (p1N, val, p2N);
965  glVertex3d (p1N-dx, val, p2N-dz);
966  }
967  }
968  else if (xyz == Z_AXIS)
969  {
970  glVertex3d (p1, p2, val);
971  glVertex3d (p1+dx, p2+dy, val);
972  if (mirror)
973  {
974  glVertex3d (p1N, p2N, val);
975  glVertex3d (p1N-dx, p2N-dy, val);
976  }
977  }
978  }
979  }
980 
981  glEnd ();
982 
983 #else
984 
985  octave_unused_parameter (ticks);
986  octave_unused_parameter (lim1);
987  octave_unused_parameter (lim2);
988  octave_unused_parameter (p1);
989  octave_unused_parameter (p1N);
990  octave_unused_parameter (p2);
991  octave_unused_parameter (p2N);
992  octave_unused_parameter (dx);
993  octave_unused_parameter (dy);
994  octave_unused_parameter (dz);
995  octave_unused_parameter (xyz);
996  octave_unused_parameter (mirror);
997 
998  // This shouldn't happen because construction of opengl_renderer
999  // objects is supposed to be impossible if OpenGL is not available.
1000 
1001  panic_impossible ();
1002 
1003 #endif
1004  }
1005 
1006  void
1008  const string_vector& ticklabels,
1009  double lim1, double lim2,
1010  double p1, double p2,
1011  int xyz, int ha, int va,
1012  int& wmax, int& hmax)
1013  {
1014 #if defined (HAVE_OPENGL)
1015 
1016  int nticks = ticks.numel ();
1017  int nlabels = ticklabels.numel ();
1018 
1019  if (nlabels == 0)
1020  return;
1021 
1022  for (int i = 0; i < nticks; i++)
1023  {
1024  double val = ticks(i);
1025 
1026  if (lim1 <= val && val <= lim2)
1027  {
1028  Matrix b;
1029 
1030  std::string label (ticklabels(i % nlabels));
1031  label.erase (0, label.find_first_not_of (" "));
1032  label = label.substr (0, label.find_last_not_of (" ")+1);
1033 
1034  // FIXME: As tick text is transparent, shouldn't it be
1035  // drawn after axes object, for correct rendering?
1036  if (xyz == X_AXIS)
1037  {
1038  b = render_text (label, val, p1, p2, ha, va);
1039  }
1040  else if (xyz == Y_AXIS)
1041  {
1042  b = render_text (label, p1, val, p2, ha, va);
1043  }
1044  else if (xyz == Z_AXIS)
1045  {
1046  b = render_text (label, p1, p2, val, ha, va);
1047  }
1048 
1049  wmax = std::max (wmax, static_cast<int> (b(2)));
1050  hmax = std::max (hmax, static_cast<int> (b(3)));
1051  }
1052  }
1053 
1054 #else
1055 
1056  octave_unused_parameter (ticks);
1057  octave_unused_parameter (ticklabels);
1058  octave_unused_parameter (lim1);
1059  octave_unused_parameter (lim2);
1060  octave_unused_parameter (p1);
1061  octave_unused_parameter (p2);
1062  octave_unused_parameter (xyz);
1063  octave_unused_parameter (ha);
1064  octave_unused_parameter (va);
1065  octave_unused_parameter (wmax);
1066  octave_unused_parameter (hmax);
1067 
1068  // This shouldn't happen because construction of opengl_renderer
1069  // objects is supposed to be impossible if OpenGL is not available.
1070 
1071  panic_impossible ();
1072 
1073 #endif
1074  }
1075 
1076  void
1078  {
1079 #if defined (HAVE_OPENGL)
1080 
1081  glFinish ();
1082 
1083 #else
1084 
1085  // This shouldn't happen because construction of opengl_renderer
1086  // objects is supposed to be impossible if OpenGL is not available.
1087 
1088  panic_impossible ();
1089 
1090 #endif
1091  }
1092 
1093  void
1095  {
1096 #if defined (HAVE_OPENGL)
1097 
1098  // setup OpenGL transformation
1099 
1100  Matrix x_zlim = props.get_transform_zlim ();
1101 
1102  xZ1 = x_zlim(0)-(x_zlim(1)-x_zlim(0))/2;
1103  xZ2 = x_zlim(1)+(x_zlim(1)-x_zlim(0))/2;
1104 
1105  Matrix x_mat1 = props.get_opengl_matrix_1 ();
1106  Matrix x_mat2 = props.get_opengl_matrix_2 ();
1107 
1108 #if defined (HAVE_FRAMEWORK_OPENGL)
1109  GLint vw[4];
1110 #else
1111  int vw[4];
1112 #endif
1113 
1114  glGetIntegerv (GL_VIEWPORT, vw);
1115 
1116  glMatrixMode (GL_MODELVIEW);
1117  glLoadIdentity ();
1118  glScaled (1, 1, -1);
1119  glMultMatrixd (x_mat1.data ());
1120  glMatrixMode (GL_PROJECTION);
1121  glLoadIdentity ();
1122  glOrtho (0, vw[2], vw[3], 0, xZ1, xZ2);
1123  glMultMatrixd (x_mat2.data ());
1124  glMatrixMode (GL_MODELVIEW);
1125 
1126  glClear (GL_DEPTH_BUFFER_BIT);
1127 
1128  // store axes transformation data
1129 
1130  xform = props.get_transform ();
1131 
1132 #else
1133 
1134  octave_unused_parameter (props);
1135 
1136  // This shouldn't happen because construction of opengl_renderer
1137  // objects is supposed to be impossible if OpenGL is not available.
1138 
1139  panic_impossible ();
1140 
1141 #endif
1142  }
1143 
1144  void
1146  {
1147 #if defined (HAVE_OPENGL)
1148 
1149  Matrix axe_color = props.get_color_rgb ();
1150  if (axe_color.is_empty () || ! props.is_visible ())
1151  return;
1152 
1153  double xPlane = props.get_xPlane ();
1154  double yPlane = props.get_yPlane ();
1155  double zPlane = props.get_zPlane ();
1156  double xPlaneN = props.get_xPlaneN ();
1157  double yPlaneN = props.get_yPlaneN ();
1158  double zPlaneN = props.get_zPlaneN ();
1159  bool is2d = props.get_is2D ();
1160 
1161  // Axes planes
1162  set_color (axe_color);
1163  set_polygon_offset (true, 2.5);
1164 
1165  glBegin (GL_QUADS);
1166 
1167  if (! is2d)
1168  {
1169  // X plane
1170  glVertex3d (xPlane, yPlaneN, zPlaneN);
1171  glVertex3d (xPlane, yPlane, zPlaneN);
1172  glVertex3d (xPlane, yPlane, zPlane);
1173  glVertex3d (xPlane, yPlaneN, zPlane);
1174 
1175  // Y plane
1176  glVertex3d (xPlaneN, yPlane, zPlaneN);
1177  glVertex3d (xPlane, yPlane, zPlaneN);
1178  glVertex3d (xPlane, yPlane, zPlane);
1179  glVertex3d (xPlaneN, yPlane, zPlane);
1180  }
1181 
1182  // Z plane
1183  glVertex3d (xPlaneN, yPlaneN, zPlane);
1184  glVertex3d (xPlane, yPlaneN, zPlane);
1185  glVertex3d (xPlane, yPlane, zPlane);
1186  glVertex3d (xPlaneN, yPlane, zPlane);
1187 
1188  glEnd ();
1189 
1190  set_polygon_offset (false);
1191 
1192 #else
1193 
1194  octave_unused_parameter (props);
1195 
1196  // This shouldn't happen because construction of opengl_renderer
1197  // objects is supposed to be impossible if OpenGL is not available.
1198 
1199  panic_impossible ();
1200 
1201 #endif
1202  }
1203 
1204  void
1206  {
1207 #if defined (HAVE_OPENGL)
1208 
1209  if (! props.is_visible ())
1210  return;
1211 
1212  bool xySym = props.get_xySym ();
1213  bool layer2Dtop = props.get_layer2Dtop ();
1214  bool is2d = props.get_is2D ();
1215  bool boxFull = (props.get_boxstyle () == "full");
1216  double linewidth = props.get_linewidth ();
1217  double xPlane = props.get_xPlane ();
1218  double yPlane = props.get_yPlane ();
1219  double zPlane = props.get_zPlane ();
1220  double xPlaneN = props.get_xPlaneN ();
1221  double yPlaneN = props.get_yPlaneN ();
1222  double zPlaneN = props.get_zPlaneN ();
1223  double xpTick = props.get_xpTick ();
1224  double ypTick = props.get_ypTick ();
1225  double zpTick = props.get_zpTick ();
1226  double xpTickN = props.get_xpTickN ();
1227  double ypTickN = props.get_ypTickN ();
1228  double zpTickN = props.get_zpTickN ();
1229 
1230  bool plotyy = (props.has_property ("__plotyy_axes__"));
1231 
1232  // Axes box
1233 
1234  set_linestyle ("-", true, linewidth);
1235 
1236  glBegin (GL_LINES);
1237 
1238  if (layer2Dtop)
1239  std::swap (zpTick, zpTickN);
1240 
1241  // X box
1242  set_color (props.get_xcolor_rgb ());
1243  glVertex3d (xPlaneN, ypTick, zpTick);
1244  glVertex3d (xPlane, ypTick, zpTick);
1245 
1246  if (props.is_box ())
1247  {
1248  glVertex3d (xPlaneN, ypTickN, zpTick);
1249  glVertex3d (xPlane, ypTickN, zpTick);
1250  if (! is2d)
1251  {
1252  glVertex3d (xPlaneN, ypTickN, zpTickN);
1253  glVertex3d (xPlane, ypTickN, zpTickN);
1254  if (boxFull)
1255  {
1256  glVertex3d (xPlaneN, ypTick, zpTickN);
1257  glVertex3d (xPlane, ypTick, zpTickN);
1258  }
1259  }
1260  }
1261 
1262  // Y box
1263  set_color (props.get_ycolor_rgb ());
1264  glVertex3d (xpTick, yPlaneN, zpTick);
1265  glVertex3d (xpTick, yPlane, zpTick);
1266 
1267  if (props.is_box () && ! plotyy)
1268  {
1269  glVertex3d (xpTickN, yPlaneN, zpTick);
1270  glVertex3d (xpTickN, yPlane, zpTick);
1271 
1272  if (! is2d)
1273  {
1274  glVertex3d (xpTickN, yPlaneN, zpTickN);
1275  glVertex3d (xpTickN, yPlane, zpTickN);
1276  if (boxFull)
1277  {
1278  glVertex3d (xpTick, yPlaneN, zpTickN);
1279  glVertex3d (xpTick, yPlane, zpTickN);
1280  }
1281  }
1282  }
1283 
1284  // Z box
1285  if (! is2d)
1286  {
1287  set_color (props.get_zcolor_rgb ());
1288 
1289  if (xySym)
1290  {
1291  glVertex3d (xPlaneN, yPlane, zPlaneN);
1292  glVertex3d (xPlaneN, yPlane, zPlane);
1293  }
1294  else
1295  {
1296  glVertex3d (xPlane, yPlaneN, zPlaneN);
1297  glVertex3d (xPlane, yPlaneN, zPlane);
1298  }
1299 
1300  if (props.is_box ())
1301  {
1302  glVertex3d (xPlane, yPlane, zPlaneN);
1303  glVertex3d (xPlane, yPlane, zPlane);
1304 
1305  if (xySym)
1306  {
1307  glVertex3d (xPlane, yPlaneN, zPlaneN);
1308  glVertex3d (xPlane, yPlaneN, zPlane);
1309  }
1310  else
1311  {
1312  glVertex3d (xPlaneN, yPlane, zPlaneN);
1313  glVertex3d (xPlaneN, yPlane, zPlane);
1314  }
1315 
1316  if (boxFull)
1317  {
1318  glVertex3d (xPlaneN, yPlaneN, zPlaneN);
1319  glVertex3d (xPlaneN, yPlaneN, zPlane);
1320  }
1321  }
1322  }
1323 
1324  glEnd ();
1325 
1326 #else
1327 
1328  octave_unused_parameter (props);
1329 
1330  // This shouldn't happen because construction of opengl_renderer
1331  // objects is supposed to be impossible if OpenGL is not available.
1332 
1333  panic_impossible ();
1334 
1335 #endif
1336  }
1337 
1338  void
1340  {
1341  int xstate = props.get_xstate ();
1342 
1343  if (props.is_visible () && xstate != AXE_DEPTH_DIR)
1344  {
1345  int zstate = props.get_zstate ();
1346  bool x2Dtop = props.get_x2Dtop ();
1347  bool layer2Dtop = props.get_layer2Dtop ();
1348  bool xyzSym = props.get_xyzSym ();
1349  bool nearhoriz = props.get_nearhoriz ();
1350  double xticklen = props.get_xticklen ();
1351  double xtickoffset = props.get_xtickoffset ();
1352  double fy = props.get_fy ();
1353  double fz = props.get_fz ();
1354  double x_min = props.get_x_min ();
1355  double x_max = props.get_x_max ();
1356  double yPlane = props.get_yPlane ();
1357  double yPlaneN = props.get_yPlaneN ();
1358  double ypTick = props.get_ypTick ();
1359  double ypTickN = props.get_ypTickN ();
1360  double zPlane = props.get_zPlane ();
1361  double zPlaneN = props.get_zPlaneN ();
1362  double zpTick = props.get_zpTick ();
1363  double zpTickN = props.get_zpTickN ();
1364 
1365  // X grid
1366 
1367  double linewidth = props.get_linewidth ();
1368  std::string gridstyle = props.get_gridlinestyle ();
1369  std::string minorgridstyle = props.get_minorgridlinestyle ();
1370  Matrix gridcolor = props.get_gridcolor_rgb ();
1371  Matrix minorgridcolor = props.get_minorgridcolor_rgb ();
1372  double gridalpha = props.get_gridalpha ();
1373  double minorgridalpha = props.get_minorgridalpha ();
1374  bool do_xgrid = (props.is_xgrid () && (gridstyle != "none"));
1375  bool do_xminorgrid = (props.is_xminorgrid ()
1376  && (minorgridstyle != "none"));
1377  bool do_xminortick = props.is_xminortick ();
1378  Matrix xticks = xform.xscale (props.get_xtick ().matrix_value ());
1379  Matrix xmticks = xform.xscale (props.get_xmtick ().matrix_value ());
1380  string_vector xticklabels = props.get_xticklabel ().string_vector_value ();
1381  int wmax = 0;
1382  int hmax = 0;
1383  bool tick_along_z = nearhoriz || octave::math::isinf (fy);
1384  bool mirror = props.is_box () && xstate != AXE_ANY_DIR;
1385 
1386  if (props.xcolormode_is ("manual"))
1387  {
1388  // use axis color for (minor)gridcolor
1389  if (props.gridcolormode_is ("auto"))
1390  gridcolor = props.get_xcolor_rgb ();
1391  if (props.minorgridcolormode_is ("auto"))
1392  minorgridcolor = props.get_xcolor_rgb ();
1393  }
1394 
1395  // set styles when drawing only minor grid
1396  if (do_xminorgrid && ! do_xgrid)
1397  {
1398  gridstyle = minorgridstyle;
1399  gridcolor = minorgridcolor;
1400  gridalpha = minorgridalpha;
1401  do_xgrid = true;
1402  }
1403 
1404  // minor grid lines
1405  if (do_xminorgrid)
1406  render_grid (linewidth,
1407  minorgridstyle, minorgridcolor, minorgridalpha,
1408  xmticks, x_min, x_max,
1409  yPlane, yPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN,
1410  0, (zstate != AXE_DEPTH_DIR));
1411 
1412  // grid lines
1413  if (do_xgrid)
1414  render_grid (linewidth,
1415  gridstyle, gridcolor, gridalpha,
1416  xticks, x_min, x_max,
1417  yPlane, yPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN,
1418  0, (zstate != AXE_DEPTH_DIR));
1419 
1420  set_color (props.get_xcolor_rgb ());
1421 
1422  // minor tick marks
1423  if (do_xminortick)
1424  {
1425  if (tick_along_z)
1426  render_tickmarks (xmticks, x_min, x_max, ypTick, ypTick,
1427  zpTick, zpTickN, 0., 0.,
1428  octave::math::signum (zpTick-zpTickN)*fz*xticklen/2,
1429  0, mirror);
1430  else
1431  render_tickmarks (xmticks, x_min, x_max, ypTick, ypTickN,
1432  zpTick, zpTick, 0.,
1433  octave::math::signum (ypTick-ypTickN)*fy*xticklen/2,
1434  0., 0, mirror);
1435  }
1436 
1437  // tick marks
1438  if (tick_along_z)
1439  {
1440  render_tickmarks (xticks, x_min, x_max, ypTick, ypTick,
1441  zpTick, zpTickN, 0., 0.,
1442  octave::math::signum (zpTick-zpTickN)*fz*xticklen,
1443  0, mirror);
1444  }
1445  else
1446  {
1447  render_tickmarks (xticks, x_min, x_max, ypTick, ypTickN,
1448  zpTick, zpTick, 0.,
1449  octave::math::signum (ypTick-ypTickN)*fy*xticklen,
1450  0., 0, mirror);
1451  }
1452 
1453  // tick texts
1454  if (xticklabels.numel () > 0)
1455  {
1456  int halign = (xstate == AXE_HORZ_DIR ? 1 : (xyzSym ? 0 : 2));
1457  int valign = (xstate == AXE_VERT_DIR ? 1 : (x2Dtop ? 0 : 2));
1458 
1459  if (tick_along_z)
1460  render_ticktexts (xticks, xticklabels, x_min, x_max, ypTick,
1461  zpTick+octave::math::signum (zpTick-zpTickN)*fz*xtickoffset,
1462  0, halign, valign, wmax, hmax);
1463  else
1464  render_ticktexts (xticks, xticklabels, x_min, x_max,
1465  ypTick+octave::math::signum (ypTick-ypTickN)*fy*xtickoffset,
1466  zpTick, 0, halign, valign, wmax, hmax);
1467  }
1468 
1469  gh_manager::get_object (props.get_xlabel ()).set ("visible", "on");
1470  }
1471  else
1472  gh_manager::get_object (props.get_xlabel ()).set ("visible", "off");
1473  }
1474 
1475  void
1477  {
1478  int ystate = props.get_ystate ();
1479 
1480  if (ystate != AXE_DEPTH_DIR && props.is_visible ())
1481  {
1482  int zstate = props.get_zstate ();
1483  bool y2Dright = props.get_y2Dright ();
1484  bool layer2Dtop = props.get_layer2Dtop ();
1485  bool xyzSym = props.get_xyzSym ();
1486  bool nearhoriz = props.get_nearhoriz ();
1487  double yticklen = props.get_yticklen ();
1488  double ytickoffset = props.get_ytickoffset ();
1489  double fx = props.get_fx ();
1490  double fz = props.get_fz ();
1491  double xPlane = props.get_xPlane ();
1492  double xPlaneN = props.get_xPlaneN ();
1493  double xpTick = props.get_xpTick ();
1494  double xpTickN = props.get_xpTickN ();
1495  double y_min = props.get_y_min ();
1496  double y_max = props.get_y_max ();
1497  double zPlane = props.get_zPlane ();
1498  double zPlaneN = props.get_zPlaneN ();
1499  double zpTick = props.get_zpTick ();
1500  double zpTickN = props.get_zpTickN ();
1501 
1502  // Y grid
1503 
1504  double linewidth = props.get_linewidth ();
1505  std::string gridstyle = props.get_gridlinestyle ();
1506  std::string minorgridstyle = props.get_minorgridlinestyle ();
1507  Matrix gridcolor = props.get_gridcolor_rgb ();
1508  Matrix minorgridcolor = props.get_minorgridcolor_rgb ();
1509  double gridalpha = props.get_gridalpha ();
1510  double minorgridalpha = props.get_minorgridalpha ();
1511  bool do_ygrid = (props.is_ygrid () && (gridstyle != "none"));
1512  bool do_yminorgrid = (props.is_yminorgrid ()
1513  && (minorgridstyle != "none"));
1514  bool do_yminortick = props.is_yminortick ();
1515  Matrix yticks = xform.yscale (props.get_ytick ().matrix_value ());
1516  Matrix ymticks = xform.yscale (props.get_ymtick ().matrix_value ());
1517  string_vector yticklabels = props.get_yticklabel ().string_vector_value ();
1518  int wmax = 0;
1519  int hmax = 0;
1520  bool tick_along_z = nearhoriz || octave::math::isinf (fx);
1521  bool mirror = props.is_box () && ystate != AXE_ANY_DIR
1522  && (! props.has_property ("__plotyy_axes__"));
1523 
1524  if (props.ycolormode_is ("manual"))
1525  {
1526  // use axis color for (minor)gridcolor
1527  if (props.gridcolormode_is ("auto"))
1528  gridcolor = props.get_ycolor_rgb ();
1529  if (props.minorgridcolormode_is ("auto"))
1530  minorgridcolor = props.get_ycolor_rgb ();
1531  }
1532 
1533  // set styles when drawing only minor grid
1534  if (do_yminorgrid && ! do_ygrid)
1535  {
1536  gridstyle = minorgridstyle;
1537  gridcolor = minorgridcolor;
1538  gridalpha = minorgridalpha;
1539  do_ygrid = true;
1540  }
1541 
1542  // minor grid lines
1543  if (do_yminorgrid)
1544  render_grid (linewidth,
1545  minorgridstyle, minorgridcolor, minorgridalpha,
1546  ymticks, y_min, y_max,
1547  xPlane, xPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN,
1548  1, (zstate != AXE_DEPTH_DIR));
1549 
1550  // grid lines
1551  if (do_ygrid)
1552  render_grid (linewidth,
1553  gridstyle, gridcolor, gridalpha,
1554  yticks, y_min, y_max,
1555  xPlane, xPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN,
1556  1, (zstate != AXE_DEPTH_DIR));
1557 
1558  set_color (props.get_ycolor_rgb ());
1559 
1560  // minor tick marks
1561  if (do_yminortick)
1562  {
1563  if (tick_along_z)
1564  render_tickmarks (ymticks, y_min, y_max, xpTick, xpTick,
1565  zpTick, zpTickN, 0., 0.,
1566  octave::math::signum (zpTick-zpTickN)*fz*yticklen/2,
1567  1, mirror);
1568  else
1569  render_tickmarks (ymticks, y_min, y_max, xpTick, xpTickN,
1570  zpTick, zpTick,
1571  octave::math::signum (xpTick-xpTickN)*fx*yticklen/2,
1572  0., 0., 1, mirror);
1573  }
1574 
1575  // tick marks
1576  if (tick_along_z)
1577  render_tickmarks (yticks, y_min, y_max, xpTick, xpTick,
1578  zpTick, zpTickN, 0., 0.,
1579  octave::math::signum (zpTick-zpTickN)*fz*yticklen,
1580  1, mirror);
1581  else
1582  render_tickmarks (yticks, y_min, y_max, xpTick, xpTickN,
1583  zpTick, zpTick,
1584  octave::math::signum (xPlaneN-xPlane)*fx*yticklen,
1585  0., 0., 1, mirror);
1586 
1587  // tick texts
1588  if (yticklabels.numel () > 0)
1589  {
1590  int halign = (ystate == AXE_HORZ_DIR
1591  ? 1 : (! xyzSym || y2Dright ? 0 : 2));
1592  int valign = (ystate == AXE_VERT_DIR ? 1 : 2);
1593 
1594  if (tick_along_z)
1595  render_ticktexts (yticks, yticklabels, y_min, y_max, xpTick,
1596  zpTick+octave::math::signum (zpTick-zpTickN)*fz*ytickoffset,
1597  1, halign, valign, wmax, hmax);
1598  else
1599  render_ticktexts (yticks, yticklabels, y_min, y_max,
1600  xpTick+octave::math::signum (xpTick-xpTickN)*fx*ytickoffset,
1601  zpTick, 1, halign, valign, wmax, hmax);
1602  }
1603 
1604  gh_manager::get_object (props.get_ylabel ()).set ("visible", "on");
1605  }
1606  else
1607  gh_manager::get_object (props.get_ylabel ()).set ("visible", "off");
1608  }
1609 
1610  void
1612  {
1613  int zstate = props.get_zstate ();
1614 
1615  if (zstate != AXE_DEPTH_DIR && props.is_visible ())
1616  {
1617  bool xySym = props.get_xySym ();
1618  bool zSign = props.get_zSign ();
1619  double zticklen = props.get_zticklen ();
1620  double ztickoffset = props.get_ztickoffset ();
1621  double fx = props.get_fx ();
1622  double fy = props.get_fy ();
1623  double xPlane = props.get_xPlane ();
1624  double xPlaneN = props.get_xPlaneN ();
1625  double yPlane = props.get_yPlane ();
1626  double yPlaneN = props.get_yPlaneN ();
1627  double z_min = props.get_z_min ();
1628  double z_max = props.get_z_max ();
1629 
1630  // Z Grid
1631 
1632  double linewidth = props.get_linewidth ();
1633  std::string gridstyle = props.get_gridlinestyle ();
1634  std::string minorgridstyle = props.get_minorgridlinestyle ();
1635  Matrix gridcolor = props.get_gridcolor_rgb ();
1636  Matrix minorgridcolor = props.get_minorgridcolor_rgb ();
1637  double gridalpha = props.get_gridalpha ();
1638  double minorgridalpha = props.get_minorgridalpha ();
1639  bool do_zgrid = (props.is_zgrid () && (gridstyle != "none"));
1640  bool do_zminorgrid = (props.is_zminorgrid ()
1641  && (minorgridstyle != "none"));
1642  bool do_zminortick = props.is_zminortick ();
1643  Matrix zticks = xform.zscale (props.get_ztick ().matrix_value ());
1644  Matrix zmticks = xform.zscale (props.get_zmtick ().matrix_value ());
1645  string_vector zticklabels = props.get_zticklabel ().string_vector_value ();
1646  int wmax = 0;
1647  int hmax = 0;
1648  bool mirror = props.is_box () && zstate != AXE_ANY_DIR;
1649 
1650  if (props.zcolormode_is ("manual"))
1651  {
1652  // use axis color for (minor)gridcolor
1653  if (props.gridcolormode_is ("auto"))
1654  gridcolor = props.get_zcolor_rgb ();
1655  if (props.minorgridcolormode_is ("auto"))
1656  minorgridcolor = props.get_zcolor_rgb ();
1657  }
1658 
1659  // set styles when drawing only minor grid
1660  if (do_zminorgrid && ! do_zgrid)
1661  {
1662  gridstyle = minorgridstyle;
1663  gridcolor = minorgridcolor;
1664  gridalpha = minorgridalpha;
1665  do_zgrid = true;
1666  }
1667 
1668  // minor grid lines
1669  if (do_zminorgrid)
1670  render_grid (linewidth,
1671  minorgridstyle, minorgridcolor, minorgridalpha,
1672  zmticks, z_min, z_max,
1673  xPlane, xPlaneN, yPlane, yPlaneN, 2, true);
1674 
1675  // grid lines
1676  if (do_zgrid)
1677  render_grid (linewidth,
1678  gridstyle, gridcolor, gridalpha,
1679  zticks, z_min, z_max,
1680  xPlane, xPlaneN, yPlane, yPlaneN, 2, true);
1681 
1682  set_color (props.get_zcolor_rgb ());
1683 
1684  // minor tick marks
1685  if (do_zminortick)
1686  {
1687  if (xySym)
1688  {
1689  if (octave::math::isinf (fy))
1690  render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlane,
1691  yPlane, yPlane,
1692  octave::math::signum (xPlaneN-xPlane)*fx*zticklen/2,
1693  0., 0., 2, mirror);
1694  else
1695  render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlaneN,
1696  yPlane, yPlane, 0.,
1697  octave::math::signum (yPlane-yPlaneN)*fy*zticklen/2,
1698  0., 2, false);
1699  }
1700  else
1701  {
1702  if (octave::math::isinf (fx))
1703  render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane,
1704  yPlaneN, yPlane, 0.,
1705  octave::math::signum (yPlaneN-yPlane)*fy*zticklen/2,
1706  0., 2, mirror);
1707  else
1708  render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane,
1709  yPlaneN, yPlaneN,
1710  octave::math::signum (xPlane-xPlaneN)*fx*zticklen/2,
1711  0., 0., 2, false);
1712  }
1713  }
1714 
1715  // tick marks
1716  if (xySym)
1717  {
1718  if (octave::math::isinf (fy))
1719  render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,
1720  yPlane, yPlane,
1721  octave::math::signum (xPlaneN-xPlane)*fx*zticklen,
1722  0., 0., 2, mirror);
1723  else
1724  render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlaneN,
1725  yPlane, yPlane, 0.,
1726  octave::math::signum (yPlane-yPlaneN)*fy*zticklen,
1727  0., 2, false);
1728  }
1729  else
1730  {
1731  if (octave::math::isinf (fx))
1732  render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,
1733  yPlaneN, yPlane, 0.,
1734  octave::math::signum (yPlaneN-yPlane)*fy*zticklen,
1735  0., 2, mirror);
1736  else
1737  render_tickmarks (zticks, z_min, z_max, xPlane, xPlane,
1738  yPlaneN, yPlane,
1739  octave::math::signum (xPlane-xPlaneN)*fx*zticklen,
1740  0., 0., 2, false);
1741  }
1742 
1743  // tick texts
1744  if (zticklabels.numel () > 0)
1745  {
1746  int halign = 2;
1747  int valign = (zstate == AXE_VERT_DIR ? 1 : (zSign ? 3 : 2));
1748 
1749  if (xySym)
1750  {
1751  if (octave::math::isinf (fy))
1752  render_ticktexts (zticks, zticklabels, z_min, z_max,
1753  xPlaneN+octave::math::signum (xPlaneN-xPlane)*fx*ztickoffset,
1754  yPlane, 2, halign, valign, wmax, hmax);
1755  else
1756  render_ticktexts (zticks, zticklabels, z_min, z_max, xPlaneN,
1757  yPlane+octave::math::signum (yPlane-yPlaneN)*fy*ztickoffset,
1758  2, halign, valign, wmax, hmax);
1759  }
1760  else
1761  {
1762  if (octave::math::isinf (fx))
1763  render_ticktexts (zticks, zticklabels, z_min, z_max, xPlane,
1764  yPlaneN+octave::math::signum (yPlaneN-yPlane)*fy*ztickoffset,
1765  2, halign, valign, wmax, hmax);
1766  else
1767  render_ticktexts (zticks, zticklabels, z_min, z_max,
1768  xPlane+octave::math::signum (xPlane-xPlaneN)*fx*ztickoffset,
1769  yPlaneN, 2, halign, valign, wmax, hmax);
1770  }
1771  }
1772 
1773  gh_manager::get_object (props.get_zlabel ()).set ("visible", "on");
1774  }
1775  else
1776  gh_manager::get_object (props.get_zlabel ()).set ("visible", "off");
1777  }
1778 
1779  void
1781  std::list<graphics_object>& obj_list)
1782  {
1783 #if defined (HAVE_OPENGL)
1784  Matrix children = props.get_all_children ();
1785 
1786  for (octave_idx_type i = children.numel () - 1; i >= 0; i--)
1787  {
1788  graphics_object go = gh_manager::get_object (children(i));
1789 
1790  if (go.get_properties ().is_visible ())
1791  {
1792  if (go.isa ("light"))
1793  {
1794  if (num_lights < max_lights)
1795  {
1796  current_light = GL_LIGHT0 + num_lights;
1798  draw (go);
1799  num_lights++;
1800  }
1801  else
1802  warning_with_id ("Octave:max-lights-exceeded",
1803  "light: Maximum number of lights (%d) in these axes is "
1804  "exceeded.", max_lights);
1805  }
1806  else if (go.isa ("hggroup"))
1807  draw_all_lights (go.get_properties (), obj_list);
1808  else
1809  obj_list.push_back (go);
1810  }
1811  }
1812 #else
1813 
1814  octave_unused_parameter (props);
1815  octave_unused_parameter (obj_list);
1816 
1817  // This shouldn't happen because construction of opengl_renderer
1818  // objects is supposed to be impossible if OpenGL is not available.
1819 
1820  panic_impossible ();
1821 
1822 #endif
1823  }
1824 
1825  void
1827  {
1828 #if defined (HAVE_OPENGL)
1829  // list for non-light child objects
1830  std::list<graphics_object> obj_list;
1831  std::list<graphics_object>::iterator it;
1832 
1833  // 1st pass: draw light objects
1834 
1835  // FIXME: max_lights only needs to be set once.
1836  // It would be better if this could be in the constructor for gl_renderer
1837  // but this seems to lead to calls of OpenGL functions before the context
1838  // is actually initialized. See bug #48669.
1839  // Check actual maximum number of lights possible
1841 
1842  // Start with the last element of the array of child objects to
1843  // display them in the order they were added to the array.
1844 
1845  num_lights = 0;
1846  draw_all_lights (props, obj_list);
1847 
1848  // disable other OpenGL lights
1849  for (int i = num_lights; i < max_lights; i++)
1850  glDisable (GL_LIGHT0 + i);
1851 
1852  // save camera position and set ambient light color before drawing
1853  // other objects
1855 
1856  float cb[4] = { 1.0, 1.0, 1.0, 1.0 };
1857  ColumnVector ambient_color = props.get_ambientlightcolor_rgb ();
1858  for (int i = 0; i < 3; i++)
1859  cb[i] = ambient_color(i);
1860  glLightfv (GL_LIGHT0, GL_AMBIENT, cb);
1861 
1862  // 2nd pass: draw other objects (with units set to "data")
1863 
1864  it = obj_list.begin ();
1865  while (it != obj_list.end ())
1866  {
1867  graphics_object go = (*it);
1868 
1869  // FIXME: check whether object has "units" property and it is set
1870  // to "data"
1871  if (! go.isa ("text") || go.get ("units").string_value () == "data")
1872  {
1874  draw (go);
1875 
1876  it = obj_list.erase (it);
1877  }
1878  else
1879  it++;
1880  }
1881 
1882  // 3rd pass: draw remaining objects
1883 
1884  glDisable (GL_DEPTH_TEST);
1885 
1886  for (it = obj_list.begin (); it != obj_list.end (); it++)
1887  {
1888  graphics_object go = (*it);
1889 
1891  draw (go);
1892  }
1893 
1894  glEnable (GL_DEPTH_TEST);
1895 
1896  set_clipping (false);
1897 
1898  // FIXME: finalize rendering (transparency processing)
1899  // FIXME: draw zoom box, if needed
1900 
1901 #else
1902 
1903  octave_unused_parameter (props);
1904 
1905  // This shouldn't happen because construction of opengl_renderer
1906  // objects is supposed to be impossible if OpenGL is not available.
1907 
1908  panic_impossible ();
1909 
1910 #endif
1911  }
1912 
1913  void
1915  {
1916 #if defined (HAVE_OPENGL)
1917 
1918  // Legends are not drawn when "visible" is "off".
1919  if (! props.is_visible () && props.get_tag () == "legend")
1920  return;
1921 
1922  static double floatmax = std::numeric_limits<float>::max ();
1923 
1924  double x_min = props.get_x_min ();
1925  double x_max = props.get_x_max ();
1926  double y_min = props.get_y_min ();
1927  double y_max = props.get_y_max ();
1928  double z_min = props.get_z_min ();
1929  double z_max = props.get_z_max ();
1930 
1931  if (x_max > floatmax || y_max > floatmax || z_max > floatmax
1932  || x_min < -floatmax || y_min < -floatmax || z_min < -floatmax)
1933  {
1934  warning ("opengl_renderer: data values greater than float capacity. (1) Scale data, or (2) Use gnuplot");
1935  return;
1936  }
1937 
1939 
1940  // Disable line smoothing for axes
1941  GLboolean antialias;
1942  glGetBooleanv (GL_LINE_SMOOTH, &antialias);
1943  if (antialias == GL_TRUE)
1944  glDisable (GL_LINE_SMOOTH);
1945 
1946  set_font (props);
1948  set_linewidth (props.get_linewidth ());
1949 
1950  // draw axes object
1951  draw_axes_planes (props);
1952 
1953  draw_axes_x_grid (props);
1954  draw_axes_y_grid (props);
1955  draw_axes_z_grid (props);
1956 
1957  if (props.get_tag () != "legend" || props.get_box () != "off")
1958  draw_axes_boxes (props);
1959 
1960  set_linestyle ("-"); // Disable LineStipple
1961 
1962  set_clipbox (x_min, x_max, y_min, y_max, z_min, z_max);
1963 
1964  // Re-enable line smoothing for children
1965  if (antialias == GL_TRUE)
1966  glEnable (GL_LINE_SMOOTH);
1967 
1968  draw_axes_children (props);
1969 
1970 #else
1971 
1972  octave_unused_parameter (props);
1973 
1974  // This shouldn't happen because construction of opengl_renderer
1975  // objects is supposed to be impossible if OpenGL is not available.
1976 
1977  panic_impossible ();
1978 
1979 #endif
1980  }
1981 
1982  void
1984  {
1985 #if defined (HAVE_OPENGL)
1986 
1987  Matrix x = xform.xscale (props.get_xdata ().matrix_value ());
1988  Matrix y = xform.yscale (props.get_ydata ().matrix_value ());
1989  Matrix z = xform.zscale (props.get_zdata ().matrix_value ());
1990 
1991  bool has_z = (z.numel () > 0);
1992  int n = static_cast<int> (std::min (std::min (x.numel (), y.numel ()),
1993  (has_z ? z.numel ()
1995  octave_uint8 clip_mask = (props.is_clipping () ? 0x7F : 0x40), clip_ok (0x40);
1996 
1997  std::vector<octave_uint8> clip (n);
1998 
1999  if (has_z)
2000  for (int i = 0; i < n; i++)
2001  clip[i] = (clip_code (x(i), y(i), z(i)) & clip_mask);
2002  else
2003  {
2004  double z_mid = (zmin+zmax)/2;
2005 
2006  for (int i = 0; i < n; i++)
2007  clip[i] = (clip_code (x(i), y(i), z_mid) & clip_mask);
2008  }
2009 
2010  if (! props.linestyle_is ("none") && ! props.color_is ("none"))
2011  {
2012  set_color (props.get_color_rgb ());
2013  set_linestyle (props.get_linestyle (), false, props.get_linewidth ());
2014  set_linewidth (props.get_linewidth ());
2015 
2016  if (has_z)
2017  {
2018  bool flag = false;
2019 
2020  for (int i = 1; i < n; i++)
2021  {
2022  if ((clip[i-1] & clip[i]) == clip_ok)
2023  {
2024  if (! flag)
2025  {
2026  flag = true;
2027  glBegin (GL_LINE_STRIP);
2028  glVertex3d (x(i-1), y(i-1), z(i-1));
2029  }
2030  glVertex3d (x(i), y(i), z(i));
2031  }
2032  else if (flag)
2033  {
2034  flag = false;
2035  glEnd ();
2036  }
2037  }
2038 
2039  if (flag)
2040  glEnd ();
2041  }
2042  else
2043  {
2044  bool flag = false;
2045 
2046  for (int i = 1; i < n; i++)
2047  {
2048  if ((clip[i-1] & clip[i]) == clip_ok)
2049  {
2050  if (! flag)
2051  {
2052  flag = true;
2053  glBegin (GL_LINE_STRIP);
2054  glVertex2d (x(i-1), y(i-1));
2055  }
2056  glVertex2d (x(i), y(i));
2057  }
2058  else if (flag)
2059  {
2060  flag = false;
2061  glEnd ();
2062  }
2063  }
2064 
2065  if (flag)
2066  glEnd ();
2067  }
2068 
2069  set_linewidth (0.5f);
2070  set_linestyle ("-");
2071  }
2072 
2073  set_clipping (false);
2074 
2075  if (! props.marker_is ("none")
2076  && ! (props.markeredgecolor_is ("none")
2077  && props.markerfacecolor_is ("none")))
2078  {
2079  Matrix lc, fc;
2080 
2081  if (props.markeredgecolor_is ("auto"))
2082  lc = props.get_color_rgb ();
2083  else if (! props.markeredgecolor_is ("none"))
2084  lc = props.get_markeredgecolor_rgb ();
2085 
2086  if (props.markerfacecolor_is ("auto"))
2087  fc = props.get_color_rgb ();
2088  else if (! props.markerfacecolor_is ("none"))
2089  fc = props.get_markerfacecolor_rgb ();
2090 
2091  init_marker (props.get_marker (), props.get_markersize (),
2092  props.get_linewidth ());
2093 
2094  for (int i = 0; i < n; i++)
2095  {
2096  if (clip[i] == clip_ok)
2097  draw_marker (x(i), y(i),
2098  has_z ? z(i) : 0.0,
2099  lc, fc);
2100  }
2101 
2102  end_marker ();
2103  }
2104 
2105  set_clipping (props.is_clipping ());
2106 
2107 #else
2108 
2109  octave_unused_parameter (props);
2110 
2111  // This shouldn't happen because construction of opengl_renderer
2112  // objects is supposed to be impossible if OpenGL is not available.
2113 
2114  panic_impossible ();
2115 
2116 #endif
2117  }
2118 
2119  void
2121  {
2122 #if defined (HAVE_OPENGL)
2123 
2124  const Matrix x = xform.xscale (props.get_xdata ().matrix_value ());
2125  const Matrix y = xform.yscale (props.get_ydata ().matrix_value ());
2126  const Matrix z = xform.zscale (props.get_zdata ().matrix_value ());
2127 
2128  int zr = z.rows ();
2129  int zc = z.columns ();
2130 
2131  NDArray c;
2132  const NDArray n = props.get_vertexnormals ().array_value ();
2133 
2134  // FIXME: handle transparency
2135  Matrix a;
2136 
2137  int fc_mode = (props.facecolor_is_rgb () ? 0 :
2138  (props.facecolor_is ("flat") ? 1 :
2139  (props.facecolor_is ("interp") ? 2 :
2140  (props.facecolor_is ("texturemap") ? 3 : -1))));
2141  int fl_mode = (props.facelighting_is ("none") ? 0 :
2142  (props.facelighting_is ("flat") ? 1 : 2));
2143  int fa_mode = (props.facealpha_is_double () ? 0 :
2144  (props.facealpha_is ("flat") ? 1 : 2));
2145  int ec_mode = (props.edgecolor_is_rgb () ? 0 :
2146  (props.edgecolor_is ("flat") ? 1 :
2147  (props.edgecolor_is ("interp") ? 2 : -1)));
2148  int el_mode = (props.edgelighting_is ("none") ? 0 :
2149  (props.edgelighting_is ("flat") ? 1 : 2));
2150  int ea_mode = (props.edgealpha_is_double () ? 0 :
2151  (props.edgealpha_is ("flat") ? 1 : 2));
2152  int bfl_mode = (props.backfacelighting_is ("lit") ? 0 :
2153  (props.backfacelighting_is ("reverselit") ? 1 : 2));
2154 
2155  Matrix fcolor = (fc_mode == TEXTURE ? Matrix (1, 3, 1.0)
2156  : props.get_facecolor_rgb ());
2157  Matrix ecolor = props.get_edgecolor_rgb ();
2158 
2159  float as = props.get_ambientstrength ();
2160  float ds = props.get_diffusestrength ();
2161  float ss = props.get_specularstrength ();
2162  float se = props.get_specularexponent () * 5; // to fit Matlab
2163  float scr = props.get_specularcolorreflectance ();
2164  float cb[4] = { 0.0, 0.0, 0.0, 1.0 };
2165 
2166  opengl_texture tex;
2167 
2168  int i1, i2, j1, j2;
2169  bool x_mat = (x.rows () == z.rows ());
2170  bool y_mat = (y.columns () == z.columns ());
2171 
2172  i1 = i2 = j1 = j2 = 0;
2173 
2174  if ((fc_mode > 0 && fc_mode < 3) || ec_mode > 0)
2175  c = props.get_color_data ().array_value ();
2176 
2177  boolMatrix clip (z.dims (), false);
2178 
2179  for (int i = 0; i < zr; i++)
2180  {
2181  if (x_mat)
2182  i1 = i;
2183 
2184  for (int j = 0; j < zc; j++)
2185  {
2186  if (y_mat)
2187  j1 = j;
2188 
2189  clip(i,j) = is_nan_or_inf (x(i1,j), y(i,j1), z(i,j));
2190  }
2191  }
2192 
2193  if (fa_mode > 0 || ea_mode > 0)
2194  {
2195  // FIXME: implement alphadata conversion
2196  //a = props.get_alpha_data ();
2197  }
2198 
2199  if (fl_mode > 0 || el_mode > 0)
2200  glMaterialf (LIGHT_MODE, GL_SHININESS, se);
2201 
2202  // FIXME: good candidate for caching,
2203  // transferring pixel data to OpenGL is time consuming.
2204  if (fc_mode == TEXTURE)
2205  tex = opengl_texture::create (props.get_color_data ());
2206 
2207  if (! props.facecolor_is ("none"))
2208  {
2209  if (props.get_facealpha_double () == 1)
2210  {
2211  if (fc_mode == UNIFORM || fc_mode == TEXTURE)
2212  {
2213  glColor3dv (fcolor.data ());
2214  if (fl_mode > 0)
2215  {
2216  for (int i = 0; i < 3; i++)
2217  cb[i] = as * fcolor(i);
2218  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
2219 
2220  for (int i = 0; i < 3; i++)
2221  cb[i] = ds * fcolor(i);
2222  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
2223 
2224  for (int i = 0; i < 3; i++)
2225  cb[i] = ss * (scr + (1-scr) * fcolor(i));
2226  glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);
2227  }
2228  }
2229 
2230  if ((fl_mode > 0) && (num_lights > 0))
2231  glEnable (GL_LIGHTING);
2232  glShadeModel ((fc_mode == INTERP || fl_mode == GOURAUD) ? GL_SMOOTH
2233  : GL_FLAT);
2234  set_polygon_offset (true, 1);
2235  if (fc_mode == TEXTURE)
2236  glEnable (GL_TEXTURE_2D);
2237 
2238  for (int i = 1; i < zc; i++)
2239  {
2240  if (y_mat)
2241  {
2242  i1 = i-1;
2243  i2 = i;
2244  }
2245 
2246  for (int j = 1; j < zr; j++)
2247  {
2248 
2249  if (clip(j-1, i-1) || clip(j, i-1)
2250  || clip(j-1, i) || clip(j, i))
2251  continue;
2252 
2253  if (fc_mode == FLAT)
2254  {
2255  // "flat" only needs color at lower-left vertex
2256  if (! octave::math::finite (c(j-1,i-1)))
2257  continue;
2258  }
2259  else if (fc_mode == INTERP)
2260  {
2261  // "interp" needs valid color at all 4 vertices
2262  if (! (octave::math::finite (c(j-1, i-1)) && octave::math::finite (c(j, i-1))
2263  && octave::math::finite (c(j-1, i)) && octave::math::finite (c(j, i))))
2264  continue;
2265  }
2266 
2267  if (x_mat)
2268  {
2269  j1 = j-1;
2270  j2 = j;
2271  }
2272 
2273  glBegin (GL_QUADS);
2274 
2275  // Vertex 1
2276  if (fc_mode == TEXTURE)
2277  tex.tex_coord (double (i-1) / (zc-1),
2278  double (j-1) / (zr-1));
2279  else if (fc_mode > 0)
2280  {
2281  // FIXME: is there a smarter way to do this?
2282  for (int k = 0; k < 3; k++)
2283  cb[k] = c(j-1, i-1, k);
2284  glColor3fv (cb);
2285 
2286  if (fl_mode > 0)
2287  {
2288  for (int k = 0; k < 3; k++)
2289  cb[k] *= as;
2290  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
2291 
2292  for (int k = 0; k < 3; k++)
2293  cb[k] = ds * c(j-1, i-1, k);
2294  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
2295 
2296  for (int k = 0; k < 3; k++)
2297  cb[k] = ss * (scr + (1-scr) * c(j-1, i-1, k));
2298  glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);
2299  }
2300  }
2301  if (fl_mode > 0)
2302  set_normal (bfl_mode, n, j-1, i-1);
2303 
2304  glVertex3d (x(j1,i-1), y(j-1,i1), z(j-1,i-1));
2305 
2306  // Vertex 2
2307  if (fc_mode == TEXTURE)
2308  tex.tex_coord (double (i) / (zc-1), double (j-1) / (zr-1));
2309  else if (fc_mode == INTERP)
2310  {
2311  for (int k = 0; k < 3; k++)
2312  cb[k] = c(j-1, i, k);
2313  glColor3fv (cb);
2314 
2315  if (fl_mode > 0)
2316  {
2317  for (int k = 0; k < 3; k++)
2318  cb[k] *= as;
2319  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
2320 
2321  for (int k = 0; k < 3; k++)
2322  cb[k] = ds * c(j-1, i, k);
2323  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
2324 
2325  for (int k = 0; k < 3; k++)
2326  cb[k] = ss * (scr + (1-scr) * c(j-1, i, k));
2327  glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);
2328  }
2329  }
2330 
2331  if (fl_mode == GOURAUD)
2332  set_normal (bfl_mode, n, j-1, i);
2333 
2334  glVertex3d (x(j1,i), y(j-1,i2), z(j-1,i));
2335 
2336  // Vertex 3
2337  if (fc_mode == TEXTURE)
2338  tex.tex_coord (double (i) / (zc-1), double (j) / (zr-1));
2339  else if (fc_mode == INTERP)
2340  {
2341  for (int k = 0; k < 3; k++)
2342  cb[k] = c(j, i, k);
2343  glColor3fv (cb);
2344 
2345  if (fl_mode > 0)
2346  {
2347  for (int k = 0; k < 3; k++)
2348  cb[k] *= as;
2349  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
2350 
2351  for (int k = 0; k < 3; k++)
2352  cb[k] = ds * c(j, i, k);
2353  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
2354 
2355  for (int k = 0; k < 3; k++)
2356  cb[k] = ss * (scr + (1-scr) * c(j, i, k));
2357  glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);
2358  }
2359  }
2360  if (fl_mode == GOURAUD)
2361  set_normal (bfl_mode, n, j, i);
2362 
2363  glVertex3d (x(j2,i), y(j,i2), z(j,i));
2364 
2365  // Vertex 4
2366  if (fc_mode == TEXTURE)
2367  tex.tex_coord (double (i-1) / (zc-1), double (j) / (zr-1));
2368  else if (fc_mode == INTERP)
2369  {
2370  for (int k = 0; k < 3; k++)
2371  cb[k] = c(j, i-1, k);
2372  glColor3fv (cb);
2373 
2374  if (fl_mode > 0)
2375  {
2376  for (int k = 0; k < 3; k++)
2377  cb[k] *= as;
2378  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
2379 
2380  for (int k = 0; k < 3; k++)
2381  cb[k] = ds * c(j, i-1, k);
2382  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
2383 
2384  for (int k = 0; k < 3; k++)
2385  cb[k] = ss * (scr + (1-scr) * c(j, i-1, k));
2386  glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);
2387  }
2388  }
2389  if (fl_mode == GOURAUD)
2390  set_normal (bfl_mode, n, j, i-1);
2391 
2392  glVertex3d (x(j2,i-1), y(j,i1), z(j,i-1));
2393 
2394  glEnd ();
2395  }
2396  }
2397 
2398  set_polygon_offset (false);
2399  if (fc_mode == TEXTURE)
2400  glDisable (GL_TEXTURE_2D);
2401 
2402  if ((fl_mode > 0) && (num_lights > 0))
2403  glDisable (GL_LIGHTING);
2404  }
2405  else
2406  {
2407  // FIXME: implement transparency
2408  }
2409  }
2410 
2411  if (! props.edgecolor_is ("none") && ! props.linestyle_is ("none"))
2412  {
2413  if (props.get_edgealpha_double () == 1)
2414  {
2415  if (ec_mode == UNIFORM)
2416  {
2417  glColor3dv (ecolor.data ());
2418  if (fl_mode > 0)
2419  {
2420  for (int i = 0; i < 3; i++)
2421  cb[i] = as * ecolor(i);
2422  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
2423 
2424  for (int i = 0; i < 3; i++)
2425  cb[i] = ds * ecolor(i);
2426  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
2427 
2428  for (int i = 0; i < 3; i++)
2429  cb[i] = ss * (scr + (1-scr) * ecolor(i));
2430  glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);
2431  }
2432  }
2433 
2434  if ((el_mode > 0) && (num_lights > 0))
2435  glEnable (GL_LIGHTING);
2436  glShadeModel ((ec_mode == INTERP || el_mode == GOURAUD) ? GL_SMOOTH
2437  : GL_FLAT);
2438 
2439  set_linestyle (props.get_linestyle (), false,
2440  props.get_linewidth ());
2441  set_linewidth (props.get_linewidth ());
2442 
2443  // Mesh along Y-axis
2444 
2445  if (props.meshstyle_is ("both") || props.meshstyle_is ("column"))
2446  {
2447  for (int i = 0; i < zc; i++)
2448  {
2449  if (y_mat)
2450  {
2451  i1 = i-1;
2452  i2 = i;
2453  }
2454 
2455  for (int j = 1; j < zr; j++)
2456  {
2457  if (clip(j-1,i) || clip(j,i))
2458  continue;
2459 
2460  if (ec_mode == FLAT)
2461  {
2462  // "flat" only needs color at lower-left vertex
2463  if (! octave::math::finite (c(j-1,i)))
2464  continue;
2465  }
2466  else if (ec_mode == INTERP)
2467  {
2468  // "interp" needs valid color at both vertices
2469  if (! (octave::math::finite (c(j-1, i)) && octave::math::finite (c(j, i))))
2470  continue;
2471  }
2472 
2473  if (x_mat)
2474  {
2475  j1 = j-1;
2476  j2 = j;
2477  }
2478 
2479  glBegin (GL_LINES);
2480 
2481  // Vertex 1
2482  if (ec_mode > 0)
2483  {
2484  for (int k = 0; k < 3; k++)
2485  cb[k] = c(j-1, i, k);
2486  glColor3fv (cb);
2487 
2488  if (el_mode > 0)
2489  {
2490  for (int k = 0; k < 3; k++)
2491  cb[k] *= as;
2492  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
2493 
2494  for (int k = 0; k < 3; k++)
2495  cb[k] = ds * c(j-1, i, k);
2496  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
2497 
2498  for (int k = 0; k < 3; k++)
2499  cb[k] = ss * (scr + (1-scr) * c(j-1, i, k));
2500  glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);
2501  }
2502  }
2503  if (el_mode > 0)
2504  set_normal (bfl_mode, n, j-1, i);
2505 
2506  glVertex3d (x(j1,i), y(j-1,i2), z(j-1,i));
2507 
2508  // Vertex 2
2509  if (ec_mode == INTERP)
2510  {
2511  for (int k = 0; k < 3; k++)
2512  cb[k] = c(j, i, k);
2513  glColor3fv (cb);
2514 
2515  if (el_mode > 0)
2516  {
2517  for (int k = 0; k < 3; k++)
2518  cb[k] *= as;
2519  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
2520 
2521  for (int k = 0; k < 3; k++)
2522  cb[k] = ds * c(j, i, k);
2523  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
2524 
2525  for (int k = 0; k < 3; k++)
2526  cb[k] = ss * (scr + (1-scr) * c(j, i, k));
2527  glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);
2528  }
2529  }
2530  if (el_mode == GOURAUD)
2531  set_normal (bfl_mode, n, j, i);
2532 
2533  glVertex3d (x(j2,i), y(j,i2), z(j,i));
2534 
2535  glEnd ();
2536  }
2537  }
2538  }
2539 
2540  // Mesh along X-axis
2541 
2542  if (props.meshstyle_is ("both") || props.meshstyle_is ("row"))
2543  {
2544  for (int j = 0; j < zr; j++)
2545  {
2546  if (x_mat)
2547  {
2548  j1 = j-1;
2549  j2 = j;
2550  }
2551 
2552  for (int i = 1; i < zc; i++)
2553  {
2554  if (clip(j,i-1) || clip(j,i))
2555  continue;
2556 
2557  if (ec_mode == FLAT)
2558  {
2559  // "flat" only needs color at lower-left vertex
2560  if (! octave::math::finite (c(j,i-1)))
2561  continue;
2562  }
2563  else if (ec_mode == INTERP)
2564  {
2565  // "interp" needs valid color at both vertices
2566  if (! (octave::math::finite (c(j, i-1)) && octave::math::finite (c(j, i))))
2567  continue;
2568  }
2569 
2570  if (y_mat)
2571  {
2572  i1 = i-1;
2573  i2 = i;
2574  }
2575 
2576  glBegin (GL_LINES);
2577 
2578  // Vertex 1
2579  if (ec_mode > 0)
2580  {
2581  for (int k = 0; k < 3; k++)
2582  cb[k] = c(j, i-1, k);
2583  glColor3fv (cb);
2584 
2585  if (el_mode > 0)
2586  {
2587  for (int k = 0; k < 3; k++)
2588  cb[k] *= as;
2589  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
2590 
2591  for (int k = 0; k < 3; k++)
2592  cb[k] = ds * c(j, i-1, k);
2593  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
2594 
2595  for (int k = 0; k < 3; k++)
2596  cb[k] = ss * (scr + (1-scr) * c(j, i-1, k));
2597  glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);
2598  }
2599  }
2600  if (el_mode > 0)
2601  set_normal (bfl_mode, n, j, i-1);
2602 
2603  glVertex3d (x(j2,i-1), y(j,i1), z(j,i-1));
2604 
2605  // Vertex 2
2606  if (ec_mode == INTERP)
2607  {
2608  for (int k = 0; k < 3; k++)
2609  cb[k] = c(j, i, k);
2610  glColor3fv (cb);
2611 
2612  if (el_mode > 0)
2613  {
2614  for (int k = 0; k < 3; k++)
2615  cb[k] *= as;
2616  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
2617 
2618  for (int k = 0; k < 3; k++)
2619  cb[k] = ds * c(j, i, k);
2620  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
2621 
2622  for (int k = 0; k < 3; k++)
2623  cb[k] = ss * (scr + (1-scr) * c(j, i, k));
2624  glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);
2625  }
2626  }
2627  if (el_mode == GOURAUD)
2628  set_normal (bfl_mode, n, j, i);
2629 
2630  glVertex3d (x(j2,i), y(j,i2), z(j,i));
2631 
2632  glEnd ();
2633  }
2634  }
2635  }
2636 
2637  set_linestyle ("-"); // Disable LineStipple
2638  set_linewidth (0.5f);
2639 
2640  if ((el_mode > 0) && (num_lights > 0))
2641  glDisable (GL_LIGHTING);
2642  }
2643  else
2644  {
2645  // FIXME: implement transparency
2646  }
2647  }
2648 
2649  if (! props.marker_is ("none")
2650  && ! (props.markeredgecolor_is ("none")
2651  && props.markerfacecolor_is ("none")))
2652  {
2653  // FIXME: check how transparency should be handled in markers
2654  // FIXME: check what to do with marker facecolor set to auto
2655  // and facecolor set to none.
2656 
2657  bool do_edge = ! props.markeredgecolor_is ("none");
2658  bool do_face = ! props.markerfacecolor_is ("none");
2659 
2660  Matrix mecolor = props.get_markeredgecolor_rgb ();
2661  Matrix mfcolor = props.get_markerfacecolor_rgb ();
2662  Matrix cc (1, 3, 0.0);
2663 
2664  if (mecolor.is_empty () && props.markeredgecolor_is ("auto"))
2665  {
2666  mecolor = props.get_edgecolor_rgb ();
2667  do_edge = ! props.edgecolor_is ("none");
2668  }
2669 
2670  if (mfcolor.is_empty () && props.markerfacecolor_is ("auto"))
2671  {
2672  mfcolor = props.get_facecolor_rgb ();
2673  do_face = ! props.facecolor_is ("none");
2674  }
2675 
2676  if ((mecolor.is_empty () || mfcolor.is_empty ()) && c.is_empty ())
2677  c = props.get_color_data ().array_value ();
2678 
2679  init_marker (props.get_marker (), props.get_markersize (),
2680  props.get_linewidth ());
2681 
2682  for (int i = 0; i < zc; i++)
2683  {
2684  if (y_mat)
2685  i1 = i;
2686 
2687  for (int j = 0; j < zr; j++)
2688  {
2689  if (clip(j,i))
2690  continue;
2691 
2692  if (x_mat)
2693  j1 = j;
2694 
2695  if ((do_edge && mecolor.is_empty ())
2696  || (do_face && mfcolor.is_empty ()))
2697  {
2698  if (! octave::math::finite (c(j,i)))
2699  continue; // Skip NaNs in color data
2700 
2701  for (int k = 0; k < 3; k++)
2702  cc(k) = c(j,i,k);
2703  }
2704 
2705  Matrix lc = (do_edge ? (mecolor.is_empty () ? cc : mecolor)
2706  : Matrix ());
2707  Matrix fc = (do_face ? (mfcolor.is_empty () ? cc : mfcolor)
2708  : Matrix ());
2709 
2710  draw_marker (x(j1,i), y(j,i1), z(j,i), lc, fc);
2711  }
2712  }
2713 
2714  end_marker ();
2715  }
2716 
2717 #else
2718 
2719  octave_unused_parameter (props);
2720 
2721  // This shouldn't happen because construction of opengl_renderer
2722  // objects is supposed to be impossible if OpenGL is not available.
2723 
2724  panic_impossible ();
2725 
2726 #endif
2727  }
2728 
2729  // FIXME: global optimization (rendering, data structures...),
2730  // there is probably a smarter/faster/less-memory-consuming way to do this.
2731  void
2733  {
2734 #if defined (HAVE_OPENGL)
2735 
2736  // Do not render if the patch has incoherent data
2737  std::string msg;
2738  if (props.has_bad_data (msg))
2739  {
2740  warning ("opengl_renderer: %s. Not rendering.", msg.c_str ());
2741  return;
2742  }
2743 
2744  const Matrix f = props.get_faces ().matrix_value ();
2745  const Matrix v = xform.scale (props.get_vertices ().matrix_value ());
2746  Matrix c;
2747  const Matrix n = props.get_vertexnormals ().matrix_value ();
2748  Matrix a;
2749 
2750  int nv = v.rows ();
2751  int nf = f.rows ();
2752  int fcmax = f.columns ();
2753 
2754  bool has_z = (v.columns () > 2);
2755  bool has_facecolor = false;
2756  bool has_facealpha = false;
2757  // FIXME: remove when patch object has normal computation (patch #8951)
2758  bool has_normals = (n.rows () == nv);
2759 
2760  int fc_mode = ((props.facecolor_is ("none")
2761  || props.facecolor_is_rgb ()) ? 0 :
2762  (props.facecolor_is ("flat") ? 1 : 2));
2763  int fl_mode = (props.facelighting_is ("none") ? 0 :
2764  (props.facelighting_is ("flat") ? 1 : 2));
2765  int fa_mode = (props.facealpha_is_double () ? 0 :
2766  (props.facealpha_is ("flat") ? 1 : 2));
2767  int ec_mode = ((props.edgecolor_is ("none")
2768  || props.edgecolor_is_rgb ()) ? 0 :
2769  (props.edgecolor_is ("flat") ? 1 : 2));
2770  int el_mode = (props.edgelighting_is ("none") ? 0 :
2771  (props.edgelighting_is ("flat") ? 1 : 2));
2772  int ea_mode = (props.edgealpha_is_double () ? 0 :
2773  (props.edgealpha_is ("flat") ? 1 : 2));
2774  int bfl_mode = (props.backfacelighting_is ("lit") ? 0 :
2775  (props.backfacelighting_is ("reverselit") ? 1 : 2));
2776 
2777  Matrix fcolor = props.get_facecolor_rgb ();
2778  Matrix ecolor = props.get_edgecolor_rgb ();
2779 
2780  float as = props.get_ambientstrength ();
2781  float ds = props.get_diffusestrength ();
2782  float ss = props.get_specularstrength ();
2783  float se = props.get_specularexponent () * 5; // to fit Matlab
2784  float scr = props.get_specularcolorreflectance ();
2785 
2786  boolMatrix clip (1, nv, false);
2787 
2788  if (has_z)
2789  for (int i = 0; i < nv; i++)
2790  clip(i) = is_nan_or_inf (v(i,0), v(i,1), v(i,2));
2791  else
2792  for (int i = 0; i < nv; i++)
2793  clip(i) = is_nan_or_inf (v(i,0), v(i,1), 0);
2794 
2795  boolMatrix clip_f (1, nf, false);
2796  Array<int> count_f (dim_vector (nf, 1), 0);
2797 
2798  for (int i = 0; i < nf; i++)
2799  {
2800  bool fclip = false;
2801  int count = 0;
2802 
2803  for (int j = 0; j < fcmax && ! octave::math::isnan (f(i,j)); j++, count++)
2804  fclip = (fclip || clip(int (f(i,j) - 1)));
2805 
2806  clip_f(i) = fclip;
2807  count_f(i) = count;
2808  }
2809 
2810  if (fc_mode > 0 || ec_mode > 0)
2811  {
2812  c = props.get_color_data ().matrix_value ();
2813 
2814  if (c.rows () == 1)
2815  {
2816  // Single color specifications, we can simplify a little bit
2817 
2818  if (fc_mode > 0)
2819  {
2820  fcolor = c;
2821  fc_mode = UNIFORM;
2822  }
2823 
2824  if (ec_mode > 0)
2825  {
2826  ecolor = c;
2827  ec_mode = UNIFORM;
2828  }
2829 
2830  c = Matrix ();
2831  }
2832  else
2833  has_facecolor = ((c.numel () > 0) && (c.rows () == f.rows ()));
2834  }
2835 
2836  if (fa_mode > 0 || ea_mode > 0)
2837  {
2838  // FIXME: retrieve alpha data from patch object
2839  //a = props.get_alpha_data ();
2840  has_facealpha = ((a.numel () > 0) && (a.rows () == f.rows ()));
2841  }
2842 
2843  octave_idx_type fr = f.rows ();
2844  std::vector<vertex_data> vdata (f.numel ());
2845 
2846  for (int i = 0; i < nf; i++)
2847  for (int j = 0; j < count_f(i); j++)
2848  {
2849  int idx = int (f(i,j) - 1);
2850 
2851  Matrix vv (1, 3, 0.0);
2852  Matrix cc;
2853  Matrix nn (1, 3, 0.0);
2854  double aa = 1.0;
2855 
2856  vv(0) = v(idx,0); vv(1) = v(idx,1);
2857  if (has_z)
2858  vv(2) = v(idx,2);
2859  if (has_normals)
2860  {
2861  double dir = 1.0;
2862  if (bfl_mode > 0)
2863  dir = ((n(idx,0) * view_vector(0)
2864  + n(idx,1) * view_vector(1)
2865  + n(idx,2) * view_vector(2) < 0)
2866  ? ((bfl_mode > 1) ? 0.0 : -1.0) : 1.0);
2867  nn(0) = dir * n(idx,0);
2868  nn(1) = dir * n(idx,1);
2869  nn(2) = dir * n(idx,2);
2870  }
2871  if (c.numel () > 0)
2872  {
2873  cc.resize (1, 3);
2874  if (has_facecolor)
2875  cc(0) = c(i,0), cc(1) = c(i,1), cc(2) = c(i,2);
2876  else
2877  cc(0) = c(idx,0), cc(1) = c(idx,1), cc(2) = c(idx,2);
2878  }
2879  if (a.numel () > 0)
2880  {
2881  if (has_facealpha)
2882  aa = a(i);
2883  else
2884  aa = a(idx);
2885  }
2886 
2887  vdata[i+j*fr] = vertex_data (vv, cc, nn, aa, as, ds, ss, se, scr);
2888  }
2889 
2890  if (fl_mode > 0 || el_mode > 0)
2891  glMaterialf (LIGHT_MODE, GL_SHININESS, se);
2892 
2893  if (! props.facecolor_is ("none"))
2894  {
2895  // FIXME: adapt to double-radio property
2896  if (props.get_facealpha_double () == 1)
2897  {
2898  if (fc_mode == UNIFORM)
2899  {
2900  glColor3dv (fcolor.data ());
2901  if (fl_mode > 0)
2902  {
2903  float cb[4] = { 0, 0, 0, 1 };
2904 
2905  for (int i = 0; i < 3; i++)
2906  cb[i] = as * fcolor(i);
2907  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
2908 
2909  for (int i = 0; i < 3; i++)
2910  cb[i] = ds * fcolor(i);
2911  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
2912 
2913  for (int i = 0; i < 3; i++)
2914  cb[i] = ss * (scr + (1-scr) * fcolor(i));
2915  glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);
2916  }
2917  }
2918 
2919  if ((fl_mode > 0) && (num_lights > 0) && has_normals)
2920  glEnable (GL_LIGHTING);
2921 
2922  // NOTE: Push filled part of patch backwards to avoid Z-fighting with
2923  // tesselator outline. A value of 1.0 seems to work fine. Value
2924  // can't be too large or the patch will be pushed below the axes
2925  // planes at +2.5.
2926  patch_tesselator tess (this, fc_mode, fl_mode, 1.0);
2927 
2928  for (int i = 0; i < nf; i++)
2929  {
2930  if (clip_f(i))
2931  continue;
2932 
2933  tess.begin_polygon (true);
2934  tess.begin_contour ();
2935 
2936  // Add vertices in reverse order for Matlab compatibility
2937  for (int j = count_f(i)-1; j > 0; j--)
2938  {
2939  vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep ();
2940 
2941  tess.add_vertex (vv->coords.fortran_vec (), vv);
2942  }
2943 
2944  if (count_f(i) > 0)
2945  {
2946  vertex_data::vertex_data_rep *vv = vdata[i].get_rep ();
2947 
2948  if (fc_mode == FLAT)
2949  {
2950  // For "flat" shading, use color of 1st vertex.
2951  Matrix col = vv->color;
2952 
2953  if (col.numel () == 3)
2954  {
2955  glColor3dv (col.data ());
2956  if (fl_mode > 0)
2957  {
2958  float cb[4] = { 0, 0, 0, 1 };
2959 
2960  for (int k = 0; k < 3; k++)
2961  cb[k] = (vv->ambient * col(k));
2962  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
2963 
2964  for (int k = 0; k < 3; k++)
2965  cb[k] = (vv->diffuse * col(k));
2966  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
2967 
2968  for (int k = 0; k < 3; k++)
2969  cb[k] = vv->specular * (vv->specular_color_refl
2970  + (1-vv->specular_color_refl) * col(k));
2971  glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);
2972  }
2973  }
2974  }
2975 
2976  tess.add_vertex (vv->coords.fortran_vec (), vv);
2977  }
2978 
2979  tess.end_contour ();
2980  tess.end_polygon ();
2981  }
2982 
2983  if ((fl_mode > 0) && (num_lights > 0) && has_normals)
2984  glDisable (GL_LIGHTING);
2985  }
2986  else
2987  {
2988  // FIXME: implement transparency
2989  }
2990  }
2991 
2992  if (! props.edgecolor_is ("none") && ! props.linestyle_is ("none"))
2993  {
2994  // FIXME: adapt to double-radio property
2995  if (props.get_edgealpha_double () == 1)
2996  {
2997  if (ec_mode == UNIFORM)
2998  {
2999  glColor3dv (ecolor.data ());
3000  if (el_mode > 0)
3001  {
3002  float cb[4] = { 0, 0, 0, 1 };
3003 
3004  for (int i = 0; i < 3; i++)
3005  cb[i] = (as * ecolor(i));
3006  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
3007 
3008  for (int i = 0; i < 3; i++)
3009  cb[i] = ds * ecolor(i);
3010  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
3011 
3012  for (int i = 0; i < 3; i++)
3013  cb[i] = ss * (scr + (1-scr) * ecolor(i));
3014  glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);
3015  }
3016  }
3017 
3018  if ((el_mode > 0) && (num_lights > 0) && has_normals)
3019  glEnable (GL_LIGHTING);
3020 
3021  double linewidth = props.get_linewidth ();
3022  set_linestyle (props.get_linestyle (), false, linewidth);
3023  set_linewidth (linewidth);
3024 
3025  // NOTE: patch contour cannot be offset. Offset must occur with the
3026  // filled portion of the patch above. The tesselator uses
3027  // GLU_TESS_BOUNDARY_ONLY to get the outline of the patch and OpenGL
3028  // automatically sets the glType to GL_LINE_LOOP. This primitive is
3029  // not supported by glPolygonOffset which is used to do Z offsets.
3030  patch_tesselator tess (this, ec_mode, el_mode);
3031 
3032  for (int i = 0; i < nf; i++)
3033  {
3034  if (clip_f(i))
3035  {
3036  // This is an unclosed contour. Draw it as a line.
3037  bool flag = false;
3038 
3039  glShadeModel ((ec_mode == INTERP || el_mode == GOURAUD)
3040  ? GL_SMOOTH : GL_FLAT);
3041 
3042  // Add vertices in reverse order for Matlab compatibility
3043  for (int j = count_f(i)-1; j >= 0; j--)
3044  {
3045  if (! clip(int (f(i,j) - 1)))
3046  {
3048  = vdata[i+j*fr].get_rep ();
3049  const Matrix m = vv->coords;
3050  if (! flag)
3051  {
3052  flag = true;
3053  glBegin (GL_LINE_STRIP);
3054  }
3055  if (ec_mode != UNIFORM)
3056  {
3057  Matrix col = vv->color;
3058 
3059  if (col.numel () == 3)
3060  glColor3dv (col.data ());
3061  }
3062  glVertex3d (m(0), m(1), m(2));
3063  }
3064  else if (flag)
3065  {
3066  flag = false;
3067  glEnd ();
3068  }
3069  }
3070  // Do loop body with vertex N to "close" GL_LINE_STRIP
3071  // from vertex 0 to vertex N.
3072  int j = count_f(i)-1;
3073  if (flag && ! clip(int (f(i,j) - 1)))
3074  {
3076  = vdata[i+j*fr].get_rep ();
3077  const Matrix m = vv->coords;
3078  if (ec_mode != UNIFORM)
3079  {
3080  Matrix col = vv->color;
3081 
3082  if (col.numel () == 3)
3083  glColor3dv (col.data ());
3084  }
3085  glVertex3d (m(0), m(1), m(2));
3086  }
3087 
3088  if (flag)
3089  glEnd ();
3090  }
3091  else // Normal edge contour drawn with tesselator
3092  {
3093  tess.begin_polygon (false);
3094  tess.begin_contour ();
3095 
3096  for (int j = count_f(i)-1; j >= 0; j--)
3097  {
3099  = vdata[i+j*fr].get_rep ();
3100  tess.add_vertex (vv->coords.fortran_vec (), vv);
3101  }
3102 
3103  tess.end_contour ();
3104  tess.end_polygon ();
3105  }
3106  }
3107 
3108  set_linestyle ("-"); // Disable LineStipple
3109  set_linewidth (0.5f);
3110 
3111  if ((el_mode > 0) && (num_lights > 0) && has_normals)
3112  glDisable (GL_LIGHTING);
3113  }
3114  else
3115  {
3116  // FIXME: implement transparency
3117  }
3118  }
3119 
3120  if (! props.marker_is ("none")
3121  && ! (props.markeredgecolor_is ("none")
3122  && props.markerfacecolor_is ("none")))
3123  {
3124  bool do_edge = ! props.markeredgecolor_is ("none");
3125  bool do_face = ! props.markerfacecolor_is ("none");
3126 
3127  Matrix mecolor = props.get_markeredgecolor_rgb ();
3128  Matrix mfcolor = props.get_markerfacecolor_rgb ();
3129 
3130  bool has_markerfacecolor = false;
3131 
3132  if ((mecolor.is_empty () && ! props.markeredgecolor_is ("none"))
3133  || (mfcolor.is_empty () && ! props.markerfacecolor_is ("none")))
3134  {
3135  Matrix mc = props.get_color_data ().matrix_value ();
3136 
3137  if (mc.rows () == 1)
3138  {
3139  // Single color specifications, we can simplify a little bit
3140  if (mfcolor.is_empty () && ! props.markerfacecolor_is ("none"))
3141  mfcolor = mc;
3142 
3143  if (mecolor.is_empty () && ! props.markeredgecolor_is ("none"))
3144  mecolor = mc;
3145  }
3146  else
3147  {
3148  if (c.is_empty ())
3149  c = props.get_color_data ().matrix_value ();
3150  has_markerfacecolor = ((c.numel () > 0)
3151  && (c.rows () == f.rows ()));
3152  }
3153  }
3154 
3155  init_marker (props.get_marker (), props.get_markersize (),
3156  props.get_linewidth ());
3157 
3158  for (int i = 0; i < nf; i++)
3159  for (int j = 0; j < count_f(i); j++)
3160  {
3161  int idx = int (f(i,j) - 1);
3162 
3163  if (clip(idx))
3164  continue;
3165 
3166  Matrix cc;
3167  if (c.numel () > 0)
3168  {
3169  cc.resize (1, 3);
3170  if (has_markerfacecolor)
3171  cc(0) = c(i,0), cc(1) = c(i,1), cc(2) = c(i,2);
3172  else
3173  cc(0) = c(idx,0), cc(1) = c(idx,1), cc(2) = c(idx,2);
3174  }
3175 
3176  Matrix lc = (do_edge ? (mecolor.is_empty () ? cc : mecolor)
3177  : Matrix ());
3178  Matrix fc = (do_face ? (mfcolor.is_empty () ? cc : mfcolor)
3179  : Matrix ());
3180 
3181  draw_marker (v(idx,0), v(idx,1), (has_z ? v(idx,2) : 0), lc, fc);
3182  }
3183 
3184  end_marker ();
3185  }
3186 
3187 #else
3188 
3189  octave_unused_parameter (props);
3190 
3191  // This shouldn't happen because construction of opengl_renderer
3192  // objects is supposed to be impossible if OpenGL is not available.
3193 
3194  panic_impossible ();
3195 
3196 #endif
3197  }
3198 
3199  void
3201  {
3202 #if defined (HAVE_OPENGL)
3203 
3204  // enable light source
3205  glEnable (current_light);
3206 
3207  // light position
3208  float pos[4] = { 0, 0, 0, 0 }; // X,Y,Z,infinite/local
3209  Matrix lpos = props.get_position ().matrix_value ();
3210  for (int i = 0; i < 3; i++)
3211  pos[i] = lpos(i);
3212  if (props.style_is ("local"))
3213  pos[3] = 1;
3214  glLightfv (current_light, GL_POSITION, pos);
3215 
3216  // light color
3217  float col[4] = { 1, 1, 1, 1 }; // R,G,B,ALPHA (the latter has no meaning)
3218  Matrix lcolor = props.get_color ().matrix_value ();
3219  for (int i = 0; i < 3; i++)
3220  col[i] = lcolor(i);
3221  glLightfv (current_light, GL_DIFFUSE, col);
3222  glLightfv (current_light, GL_SPECULAR, col);
3223 
3224 #else
3225 
3226  octave_unused_parameter (props);
3227 
3228  // This shouldn't happen because construction of opengl_renderer
3229  // objects is supposed to be impossible if OpenGL is not available.
3230 
3231  panic_impossible ();
3232 
3233 #endif
3234  }
3235 
3236  void
3238  {
3239  draw (props.get_children ());
3240  }
3241 
3242  void
3244  {
3245 #if defined (HAVE_OPENGL)
3246 
3247  if (props.get_string ().is_empty ())
3248  return;
3249 
3250  set_font (props);
3251 
3252  Matrix pos = xform.scale (props.get_data_position ());
3253  const Matrix bbox = props.get_extent_matrix ();
3254 
3255  // FIXME: handle margin and surrounding box
3256  bool blend = glIsEnabled (GL_BLEND);
3257 
3258  glEnable (GL_BLEND);
3259  glEnable (GL_ALPHA_TEST);
3260  glRasterPos3d (pos(0), pos(1), pos.numel () > 2 ? pos(2) : 0.0);
3261  glBitmap (0, 0, 0, 0, bbox(0), bbox(1), 0);
3262  glDrawPixels (bbox(2), bbox(3),
3263  GL_RGBA, GL_UNSIGNED_BYTE, props.get_pixels ().data ());
3264  glDisable (GL_ALPHA_TEST);
3265  if (! blend)
3266  glDisable (GL_BLEND);
3267 
3268 #else
3269 
3270  octave_unused_parameter (props);
3271 
3272  // This shouldn't happen because construction of opengl_renderer
3273  // objects is supposed to be impossible if OpenGL is not available.
3274 
3275  panic_impossible ();
3276 
3277 #endif
3278  }
3279 
3280  void
3282  {
3283 #if defined (HAVE_OPENGL)
3284 
3285  octave_value cdata = props.get_color_data ();
3286  dim_vector dv (cdata.dims ());
3287  int h = dv(0);
3288  int w = dv(1);
3289 
3290  Matrix x = props.get_xdata ().matrix_value ();
3291  Matrix y = props.get_ydata ().matrix_value ();
3292 
3293  // Someone wants us to draw an empty image? No way.
3294  if (x.is_empty () || y.is_empty ())
3295  return;
3296 
3297  if (w > 1 && x(1) == x(0))
3298  x(1) = x(1) + (w-1);
3299 
3300  if (h > 1 && y(1) == y(0))
3301  y(1) = y(1) + (h-1);
3302 
3303  const ColumnVector p0 = xform.transform (x(0), y(0), 0);
3304  const ColumnVector p1 = xform.transform (x(1), y(1), 0);
3305 
3306  if (octave::math::isnan (p0(0)) || octave::math::isnan (p0(1))
3307  || octave::math::isnan (p1(0)) || octave::math::isnan (p1(1)))
3308  {
3309  warning ("opengl_renderer: image X,Y data too large to draw");
3310  return;
3311  }
3312 
3313  // image pixel size in screen pixel units
3314  float pix_dx, pix_dy;
3315  // image pixel size in normalized units
3316  float nor_dx, nor_dy;
3317 
3318  if (w > 1)
3319  {
3320  pix_dx = (p1(0) - p0(0)) / (w-1);
3321  nor_dx = (x(1) - x(0)) / (w-1);
3322  }
3323  else
3324  {
3325  const ColumnVector p1w = xform.transform (x(1) + 1, y(1), 0);
3326  pix_dx = p1w(0) - p0(0);
3327  nor_dx = 1;
3328  }
3329 
3330  if (h > 1)
3331  {
3332  pix_dy = (p1(1) - p0(1)) / (h-1);
3333  nor_dy = (y(1) - y(0)) / (h-1);
3334  }
3335  else
3336  {
3337  const ColumnVector p1h = xform.transform (x(1), y(1) + 1, 0);
3338  pix_dy = p1h(1) - p0(1);
3339  nor_dy = 1;
3340  }
3341 
3342  // OpenGL won't draw any of the image if its origin is outside the
3343  // viewport/clipping plane so we must do the clipping ourselves.
3344 
3345  int j0, j1, i0, i1;
3346  j0 = 0, j1 = w;
3347  i0 = 0, i1 = h;
3348 
3349  float im_xmin = x(0) - nor_dx/2;
3350  float im_xmax = x(1) + nor_dx/2;
3351  float im_ymin = y(0) - nor_dy/2;
3352  float im_ymax = y(1) + nor_dy/2;
3353  if (props.is_clipping ()) // clip to axes
3354  {
3355  if (im_xmin < xmin)
3356  j0 += (xmin - im_xmin)/nor_dx + 1;
3357  if (im_xmax > xmax)
3358  j1 -= (im_xmax - xmax)/nor_dx;
3359 
3360  if (im_ymin < ymin)
3361  i0 += (ymin - im_ymin)/nor_dy + 1;
3362  if (im_ymax > ymax)
3363  i1 -= (im_ymax - ymax)/nor_dy;
3364  }
3365  else // clip to viewport
3366  {
3367  GLfloat vp[4];
3368  glGetFloatv (GL_VIEWPORT, vp);
3369  // FIXME: actually add the code to do it!
3370  }
3371 
3372  if (i0 >= i1 || j0 >= j1)
3373  return;
3374 
3375  glPixelZoom (pix_dx, -pix_dy);
3376  glRasterPos3d (im_xmin + nor_dx*j0, im_ymin + nor_dy*i0, 0);
3377 
3378  // by default this is 4
3379  glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
3380 
3381  // Expect RGB data
3382  if (dv.ndims () == 3 && dv(2) == 3)
3383  {
3384  if (cdata.is_double_type ())
3385  {
3386  const NDArray xcdata = cdata.array_value ();
3387 
3388  OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0));
3389 
3390  for (int i = i0; i < i1; i++)
3391  {
3392  for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
3393  {
3394  a[idx] = xcdata(i,j,0);
3395  a[idx+1] = xcdata(i,j,1);
3396  a[idx+2] = xcdata(i,j,2);
3397  }
3398  }
3399 
3400  draw_pixels (j1-j0, i1-i0, a);
3401 
3402  }
3403  else if (cdata.is_single_type ())
3404  {
3405  const FloatNDArray xcdata = cdata.float_array_value ();
3406 
3407  OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0));
3408 
3409  for (int i = i0; i < i1; i++)
3410  {
3411  for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
3412  {
3413  a[idx] = xcdata(i,j,0);
3414  a[idx+1] = xcdata(i,j,1);
3415  a[idx+2] = xcdata(i,j,2);
3416  }
3417  }
3418 
3419  draw_pixels (j1-j0, i1-i0, a);
3420 
3421  }
3422  else if (cdata.is_uint8_type ())
3423  {
3424  const uint8NDArray xcdata = cdata.uint8_array_value ();
3425 
3426  OCTAVE_LOCAL_BUFFER (GLubyte, a, 3*(j1-j0)*(i1-i0));
3427 
3428  for (int i = i0; i < i1; i++)
3429  {
3430  for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
3431  {
3432  a[idx] = xcdata(i,j,0);
3433  a[idx+1] = xcdata(i,j,1);
3434  a[idx+2] = xcdata(i,j,2);
3435  }
3436  }
3437 
3438  draw_pixels (j1-j0, i1-i0, a);
3439 
3440  }
3441  else if (cdata.is_uint16_type ())
3442  {
3443  const uint16NDArray xcdata = cdata.uint16_array_value ();
3444 
3445  OCTAVE_LOCAL_BUFFER (GLushort, a, 3*(j1-j0)*(i1-i0));
3446 
3447  for (int i = i0; i < i1; i++)
3448  {
3449  for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
3450  {
3451  a[idx] = xcdata(i,j,0);
3452  a[idx+1] = xcdata(i,j,1);
3453  a[idx+2] = xcdata(i,j,2);
3454  }
3455  }
3456 
3457  draw_pixels (j1-j0, i1-i0, a);
3458 
3459  }
3460  else
3461  warning ("opengl_renderer: invalid image data type (expected double, single, uint8, or uint16)");
3462  }
3463  else
3464  warning ("opengl_renderer: invalid image size (expected MxNx3 or MxN)");
3465 
3466  glPixelZoom (1, 1);
3467 
3468 #else
3469 
3470  octave_unused_parameter (props);
3471 
3472  // This shouldn't happen because construction of opengl_renderer
3473  // objects is supposed to be impossible if OpenGL is not available.
3474 
3475  panic_impossible ();
3476 
3477 #endif
3478  }
3479 
3480  void
3482  {
3483 #if defined (HAVE_OPENGL)
3484 
3485  glViewport (0, 0, w, h);
3486 
3487 #else
3488 
3489  octave_unused_parameter (w);
3490  octave_unused_parameter (h);
3491 
3492  // This shouldn't happen because construction of opengl_renderer
3493  // objects is supposed to be impossible if OpenGL is not available.
3494 
3495  panic_impossible ();
3496 
3497 #endif
3498  }
3499 
3500  void
3501  opengl_renderer::draw_pixels (int width, int height, const float *data)
3502  {
3503 #if defined (HAVE_OPENGL)
3504 
3505  glDrawPixels (width, height, GL_RGB, GL_FLOAT, data);
3506 
3507 #else
3508 
3509  octave_unused_parameter (width);
3510  octave_unused_parameter (height);
3511  octave_unused_parameter (data);
3512 
3513  // This shouldn't happen because construction of opengl_renderer
3514  // objects is supposed to be impossible if OpenGL is not available.
3515 
3516  panic_impossible ();
3517 
3518 #endif
3519  }
3520 
3521  void
3522  opengl_renderer::draw_pixels (int width, int height, const uint8_t *data)
3523  {
3524 #if defined (HAVE_OPENGL)
3525 
3526  glDrawPixels (width, height, GL_RGB, GL_UNSIGNED_BYTE, data);
3527 
3528 #else
3529 
3530  octave_unused_parameter (width);
3531  octave_unused_parameter (height);
3532  octave_unused_parameter (data);
3533 
3534  // This shouldn't happen because construction of opengl_renderer
3535  // objects is supposed to be impossible if OpenGL is not available.
3536 
3537  panic_impossible ();
3538 
3539 #endif
3540  }
3541 
3542  void
3543  opengl_renderer::draw_pixels (int width, int height, const uint16_t *data)
3544  {
3545 #if defined (HAVE_OPENGL)
3546 
3547  glDrawPixels (width, height, GL_RGB, GL_UNSIGNED_SHORT, data);
3548 
3549 #else
3550 
3551  octave_unused_parameter (width);
3552  octave_unused_parameter (height);
3553  octave_unused_parameter (data);
3554 
3555  // This shouldn't happen because construction of opengl_renderer
3556  // objects is supposed to be impossible if OpenGL is not available.
3557 
3558  panic_impossible ();
3559 
3560 #endif
3561  }
3562 
3563  void
3565  {
3566 #if defined (HAVE_OPENGL)
3567 
3568  glColor3dv (c.data ());
3569 
3570  txt_renderer.set_color (c);
3571 
3572 #else
3573 
3574  octave_unused_parameter (c);
3575 
3576  // This shouldn't happen because construction of opengl_renderer
3577  // objects is supposed to be impossible if OpenGL is not available.
3578 
3579  panic_impossible ();
3580 
3581 #endif
3582  }
3583 
3584  void
3586  {
3587  txt_renderer.set_font (props.get ("fontname").string_value (),
3588  props.get ("fontweight").string_value (),
3589  props.get ("fontangle").string_value (),
3590  props.get ("fontsize_points").double_value ());
3591  }
3592 
3593  void
3594  opengl_renderer::set_polygon_offset (bool on, float offset)
3595  {
3596 #if defined (HAVE_OPENGL)
3597 
3598  if (on)
3599  {
3600  glEnable (GL_POLYGON_OFFSET_FILL);
3601  glEnable (GL_POLYGON_OFFSET_LINE);
3602  glPolygonOffset (offset, offset);
3603  }
3604  else
3605  {
3606  glDisable (GL_POLYGON_OFFSET_FILL);
3607  glDisable (GL_POLYGON_OFFSET_LINE);
3608  }
3609 
3610 #else
3611 
3612  octave_unused_parameter (on);
3613  octave_unused_parameter (offset);
3614 
3615  // This shouldn't happen because construction of opengl_renderer
3616  // objects is supposed to be impossible if OpenGL is not available.
3617 
3618  panic_impossible ();
3619 
3620 #endif
3621  }
3622 
3623  void
3625  {
3626 #if defined (HAVE_OPENGL)
3627 
3628  glLineWidth (w);
3629 
3630 #else
3631 
3632  octave_unused_parameter (w);
3633 
3634  // This shouldn't happen because construction of opengl_renderer
3635  // objects is supposed to be impossible if OpenGL is not available.
3636 
3637  panic_impossible ();
3638 
3639 #endif
3640  }
3641 
3642  void
3643  opengl_renderer::set_linestyle (const std::string& s, bool use_stipple,
3644  double linewidth)
3645  {
3646 #if defined (HAVE_OPENGL)
3647 
3648  bool solid = false;
3649 
3650  if (s == "-")
3651  {
3652  glLineStipple (1, static_cast<unsigned short> (0xFFFF));
3653  solid = true;
3654  }
3655  else if (s == ":")
3656  glLineStipple (linewidth, static_cast<unsigned short> (0x5555));
3657  else if (s == "--")
3658  glLineStipple (linewidth, static_cast<unsigned short> (0x0F0F));
3659  else if (s == "-.")
3660  glLineStipple (linewidth, static_cast<unsigned short> (0x6F6F));
3661  else
3662  glLineStipple (1, static_cast<unsigned short> (0x0000));
3663 
3664  if (solid && ! use_stipple)
3665  glDisable (GL_LINE_STIPPLE);
3666  else
3667  glEnable (GL_LINE_STIPPLE);
3668 
3669 #else
3670 
3671  octave_unused_parameter (s);
3672  octave_unused_parameter (use_stipple);
3673  octave_unused_parameter (linewidth);
3674 
3675  // This shouldn't happen because construction of opengl_renderer
3676  // objects is supposed to be impossible if OpenGL is not available.
3677 
3678  panic_impossible ();
3679 
3680 #endif
3681  }
3682 
3683  void
3684  opengl_renderer::set_clipbox (double x1, double x2, double y1, double y2,
3685  double z1, double z2)
3686  {
3687 #if defined (HAVE_OPENGL)
3688 
3689  double dx = (x2-x1);
3690  double dy = (y2-y1);
3691  double dz = (z2-z1);
3692 
3693  x1 -= 0.001*dx; x2 += 0.001*dx;
3694  y1 -= 0.001*dy; y2 += 0.001*dy;
3695  z1 -= 0.001*dz; z2 += 0.001*dz;
3696 
3697  ColumnVector p (4, 0.0);
3698 
3699  p(0) = -1; p(3) = x2;
3700  glClipPlane (GL_CLIP_PLANE0, p.data ());
3701  p(0) = 1; p(3) = -x1;
3702  glClipPlane (GL_CLIP_PLANE1, p.data ());
3703  p(0) = 0; p(1) = -1; p(3) = y2;
3704  glClipPlane (GL_CLIP_PLANE2, p.data ());
3705  p(1) = 1; p(3) = -y1;
3706  glClipPlane (GL_CLIP_PLANE3, p.data ());
3707  p(1) = 0; p(2) = -1; p(3) = z2;
3708  glClipPlane (GL_CLIP_PLANE4, p.data ());
3709  p(2) = 1; p(3) = -z1;
3710  glClipPlane (GL_CLIP_PLANE5, p.data ());
3711 
3712  xmin = x1; xmax = x2;
3713  ymin = y1; ymax = y2;
3714  zmin = z1; zmax = z2;
3715 
3716 #else
3717 
3718  octave_unused_parameter (x1);
3719  octave_unused_parameter (x2);
3720  octave_unused_parameter (y1);
3721  octave_unused_parameter (y2);
3722  octave_unused_parameter (z1);
3723  octave_unused_parameter (z2);
3724 
3725  // This shouldn't happen because construction of opengl_renderer
3726  // objects is supposed to be impossible if OpenGL is not available.
3727 
3728  panic_impossible ();
3729 
3730 #endif
3731  }
3732 
3733  void
3735  {
3736 #if defined (HAVE_OPENGL)
3737 
3738  bool has_clipping = (glIsEnabled (GL_CLIP_PLANE0) == GL_TRUE);
3739 
3740  if (enable != has_clipping)
3741  {
3742  if (enable)
3743  for (int i = 0; i < 6; i++)
3744  glEnable (GL_CLIP_PLANE0+i);
3745  else
3746  for (int i = 0; i < 6; i++)
3747  glDisable (GL_CLIP_PLANE0+i);
3748  }
3749 
3750 #else
3751 
3752  octave_unused_parameter (enable);
3753 
3754  // This shouldn't happen because construction of opengl_renderer
3755  // objects is supposed to be impossible if OpenGL is not available.
3756 
3757  panic_impossible ();
3758 
3759 #endif
3760  }
3761 
3762  void
3763  opengl_renderer::init_marker (const std::string& m, double size, float width)
3764  {
3765 #if defined (HAVE_OPENGL)
3766 
3767 # if defined (HAVE_FRAMEWORK_OPENGL)
3768  GLint vw[4];
3769 # else
3770  int vw[4];
3771 # endif
3772 
3773  glGetIntegerv (GL_VIEWPORT, vw);
3774 
3775  glMatrixMode (GL_PROJECTION);
3776  glPushMatrix ();
3777  glLoadIdentity ();
3778  glOrtho (0, vw[2], vw[3], 0, xZ1, xZ2);
3779  glMatrixMode (GL_MODELVIEW);
3780  glPushMatrix ();
3781 
3782  set_clipping (false);
3783  set_linewidth (width);
3784 
3785  marker_id = make_marker_list (m, size, false);
3786  filled_marker_id = make_marker_list (m, size, true);
3787 
3788 #else
3789 
3790  octave_unused_parameter (m);
3791  octave_unused_parameter (size);
3792  octave_unused_parameter (width);
3793 
3794  // This shouldn't happen because construction of opengl_renderer
3795  // objects is supposed to be impossible if OpenGL is not available.
3796 
3797  panic_impossible ();
3798 
3799 #endif
3800  }
3801 
3802  void
3804  {
3805 #if defined (HAVE_OPENGL)
3806 
3807  glDeleteLists (marker_id, 1);
3808  glDeleteLists (filled_marker_id, 1);
3809 
3810  glMatrixMode (GL_MODELVIEW);
3811  glPopMatrix ();
3812  glMatrixMode (GL_PROJECTION);
3813  glPopMatrix ();
3814  set_linewidth (0.5f);
3815 
3816 #else
3817 
3818  // This shouldn't happen because construction of opengl_renderer
3819  // objects is supposed to be impossible if OpenGL is not available.
3820 
3821  panic_impossible ();
3822 
3823 #endif
3824  }
3825 
3826  void
3827  opengl_renderer::draw_marker (double x, double y, double z,
3828  const Matrix& lc, const Matrix& fc)
3829  {
3830 #if defined (HAVE_OPENGL)
3831 
3832  ColumnVector tmp = xform.transform (x, y, z, false);
3833 
3834  glLoadIdentity ();
3835  glTranslated (tmp(0), tmp(1), -tmp(2));
3836 
3837  if (filled_marker_id > 0 && fc.numel () > 0)
3838  {
3839  glColor3dv (fc.data ());
3840  set_polygon_offset (true, -1.0);
3841  glCallList (filled_marker_id);
3842  if (lc.numel () > 0)
3843  {
3844  glColor3dv (lc.data ());
3845  glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
3846  glEdgeFlag (GL_TRUE);
3847  set_polygon_offset (true, -2.0);
3848  glCallList (filled_marker_id);
3849  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
3850  }
3851  set_polygon_offset (false);
3852  }
3853  else if (marker_id > 0 && lc.numel () > 0)
3854  {
3855  glColor3dv (lc.data ());
3856  glCallList (marker_id);
3857  }
3858 
3859 #else
3860 
3861  octave_unused_parameter (x);
3862  octave_unused_parameter (y);
3863  octave_unused_parameter (z);
3864  octave_unused_parameter (lc);
3865  octave_unused_parameter (fc);
3866 
3867  // This shouldn't happen because construction of opengl_renderer
3868  // objects is supposed to be impossible if OpenGL is not available.
3869 
3870  panic_impossible ();
3871 
3872 #endif
3873  }
3874 
3875  void
3876  opengl_renderer::set_normal (int bfl_mode, const NDArray& n, int j, int i)
3877  {
3878 #if defined (HAVE_OPENGL)
3879 
3880  double x = n(j,i,0);
3881  double y = n(j,i,1);
3882  double z = n(j,i,2);
3883 
3884  double d = sqrt (x*x + y*y + z*z);
3885 
3886  double dir = 1.0;
3887 
3888  if (bfl_mode > 0)
3889  dir = ((x * view_vector(0) + y * view_vector(1) + z * view_vector(2) < 0)
3890  ? ((bfl_mode > 1) ? 0.0 : -1.0) : 1.0);
3891 
3892  glNormal3d (dir*x/d, dir*y/d, dir*z/d);
3893 
3894 #else
3895 
3896  octave_unused_parameter (bfl_mode);
3897  octave_unused_parameter (n);
3898  octave_unused_parameter (j);
3899  octave_unused_parameter (i);
3900 
3901  // This shouldn't happen because construction of opengl_renderer
3902  // objects is supposed to be impossible if OpenGL is not available.
3903 
3904  panic_impossible ();
3905 
3906 #endif
3907  }
3908 
3909  unsigned int
3911  bool filled) const
3912  {
3913 #if defined (HAVE_OPENGL)
3914 
3915  char c = marker[0];
3916 
3917  if (filled && (c == '+' || c == 'x' || c == '*' || c == '.'))
3918  return 0;
3919 
3920  unsigned int ID = glGenLists (1);
3921  double sz = size * toolkit.get_screen_resolution () / 72.0;
3922 
3923  // constants for the * marker
3924  const double sqrt2d4 = 0.35355339059327;
3925  double tt = sz*sqrt2d4;
3926 
3927  glNewList (ID, GL_COMPILE);
3928 
3929  switch (marker[0])
3930  {
3931  case '+':
3932  glBegin (GL_LINES);
3933  glVertex2d (-sz/2, 0);
3934  glVertex2d (sz/2, 0);
3935  glVertex2d (0, -sz/2);
3936  glVertex2d (0, sz/2);
3937  glEnd ();
3938  break;
3939  case 'x':
3940  glBegin (GL_LINES);
3941  glVertex2d (-sz/2, -sz/2);
3942  glVertex2d (sz/2, sz/2);
3943  glVertex2d (-sz/2, sz/2);
3944  glVertex2d (sz/2, -sz/2);
3945  glEnd ();
3946  break;
3947  case '*':
3948  glBegin (GL_LINES);
3949  glVertex2d (-sz/2, 0);
3950  glVertex2d (sz/2, 0);
3951  glVertex2d (0, -sz/2);
3952  glVertex2d (0, sz/2);
3953  glVertex2d (-tt, -tt);
3954  glVertex2d (+tt, +tt);
3955  glVertex2d (-tt, +tt);
3956  glVertex2d (+tt, -tt);
3957  glEnd ();
3958  break;
3959  case '.':
3960  {
3961  // The dot marker is special and is drawn at 1/3rd the specified size
3962 
3963  // Ensure that something is drawn even at very small markersizes
3964  if (sz > 0 && sz < 3)
3965  sz = 3;
3966 
3967  int div = static_cast <int> (M_PI * sz / 12);
3968  if (! (div % 2))
3969  div += 1; // ensure odd number for left/right symmetry
3970  div = std::max (div, 3); // ensure at least a few vertices are drawn
3971  double ang_step = M_PI / div;
3972 
3973  glBegin (GL_POLYGON);
3974  for (double ang = 0; ang < 2*M_PI; ang += ang_step)
3975  glVertex2d (sz/6*cos (ang), sz/6*sin (ang));
3976  glEnd ();
3977  }
3978  break;
3979  case 's':
3980  glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);
3981  glVertex2d (-sz/2, -sz/2);
3982  glVertex2d (-sz/2, sz/2);
3983  glVertex2d (sz/2, sz/2);
3984  glVertex2d (sz/2, -sz/2);
3985  glEnd ();
3986  break;
3987  case 'o':
3988  {
3989  int div = static_cast <int> (M_PI * sz / 4);
3990  if (! (div % 2))
3991  div += 1; // ensure odd number for left/right symmetry
3992  div = std::max (div, 5); // ensure at least a few vertices are drawn
3993  double ang_step = M_PI / div;
3994 
3995  glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);
3996  for (double ang = 0; ang < 2*M_PI; ang += ang_step)
3997  glVertex2d (sz/2*cos (ang), sz/2*sin (ang));
3998  glEnd ();
3999  }
4000  break;
4001  case 'd':
4002  glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);
4003  glVertex2d (0, -sz/2);
4004  glVertex2d (sz/2, 0);
4005  glVertex2d (0, sz/2);
4006  glVertex2d (-sz/2, 0);
4007  glEnd ();
4008  break;
4009  case 'v':
4010  glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);
4011  glVertex2d (0, sz/2);
4012  glVertex2d (sz/2, -sz/2);
4013  glVertex2d (-sz/2, -sz/2);
4014  glEnd ();
4015  break;
4016  case '^':
4017  glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);
4018  glVertex2d (0, -sz/2);
4019  glVertex2d (-sz/2, sz/2);
4020  glVertex2d (sz/2, sz/2);
4021  glEnd ();
4022  break;
4023  case '>':
4024  glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);
4025  glVertex2d (sz/2, 0);
4026  glVertex2d (-sz/2, sz/2);
4027  glVertex2d (-sz/2, -sz/2);
4028  glEnd ();
4029  break;
4030  case '<':
4031  glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);
4032  glVertex2d (-sz/2, 0);
4033  glVertex2d (sz/2, -sz/2);
4034  glVertex2d (sz/2, sz/2);
4035  glEnd ();
4036  break;
4037  case 'p':
4038  {
4039  double ang, r, dr;
4040  dr = 1.0 - sin (M_PI/10)/sin (3*M_PI/10)*1.02;
4041 
4042  glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);
4043  for (int i = 0; i < 2*5; i++)
4044  {
4045  ang = (-0.5 + double (i+1) / 5) * M_PI;
4046  r = 1.0 - (dr * fmod (double (i+1), 2.0));
4047  glVertex2d (sz/2*r*cos (ang), sz/2*r*sin (ang));
4048  }
4049  glEnd ();
4050  }
4051  break;
4052  case 'h':
4053  {
4054  double ang, r, dr;
4055  dr = 1.0 - 0.5/sin (M_PI/3)*1.02;
4056 
4057  glBegin (filled ? GL_POLYGON : GL_LINE_LOOP);
4058  for (int i = 0; i < 2*6; i++)
4059  {
4060  ang = (0.5 + double (i+1) / 6.0) * M_PI;
4061  r = 1.0 - (dr * fmod (double (i+1), 2.0));
4062  glVertex2d (sz/2*r*cos (ang), sz/2*r*sin (ang));
4063  }
4064  glEnd ();
4065  }
4066  break;
4067  default:
4068  warning ("opengl_renderer: unsupported marker '%s'", marker.c_str ());
4069  break;
4070  }
4071 
4072  glEndList ();
4073 
4074  return ID;
4075 
4076 #else
4077 
4078  octave_unused_parameter (marker);
4079  octave_unused_parameter (size);
4080  octave_unused_parameter (filled);
4081 
4082  // This shouldn't happen because construction of opengl_renderer
4083  // objects is supposed to be impossible if OpenGL is not available.
4084 
4085  panic_impossible ();
4086 
4087 #endif
4088  }
4089 
4090  void
4092  uint8NDArray& pixels,
4093  Matrix& bbox,
4094  int halign, int valign, double rotation)
4095  {
4096  txt_renderer.text_to_pixels (txt, pixels, bbox, halign, valign,
4097  rotation, interpreter);
4098  }
4099 
4100  void
4102  std::list<text_renderer::string>& lst,
4103  Matrix& bbox,
4104  int halign, int valign, double rotation)
4105  {
4106  txt_renderer.text_to_strlist (txt, lst, bbox, halign, valign,
4107  rotation, interpreter);
4108  }
4109 
4110  Matrix
4112  double x, double y, double z,
4113  int halign, int valign, double rotation)
4114  {
4115 #if defined (HAVE_OPENGL)
4116 
4117  Matrix bbox (1, 4, 0.0);
4118 
4119  if (txt.empty ())
4120  return bbox;
4121 
4122  if (txt_renderer.ok ())
4123  {
4124  uint8NDArray pixels;
4125  text_to_pixels (txt, pixels, bbox, halign, valign, rotation);
4126 
4127  bool blend = glIsEnabled (GL_BLEND);
4128 
4129  glEnable (GL_BLEND);
4130  glEnable (GL_ALPHA_TEST);
4131  glRasterPos3d (x, y, z);
4132  glBitmap(0, 0, 0, 0, bbox(0), bbox(1), 0);
4133  glDrawPixels (bbox(2), bbox(3),
4134  GL_RGBA, GL_UNSIGNED_BYTE, pixels.data ());
4135  glDisable (GL_ALPHA_TEST);
4136 
4137  if (! blend)
4138  glDisable (GL_BLEND);
4139  }
4140 
4141  return bbox;
4142 
4143 #else
4144 
4145  octave_unused_parameter (txt);
4146  octave_unused_parameter (x);
4147  octave_unused_parameter (y);
4148  octave_unused_parameter (z);
4149  octave_unused_parameter (halign);
4150  octave_unused_parameter (valign);
4151  octave_unused_parameter (rotation);
4152 
4153  // This shouldn't happen because construction of opengl_renderer
4154  // objects is supposed to be impossible if OpenGL is not available.
4155 
4156  panic_impossible ();
4157 
4158 #endif
4159  }
4160 }
uint32_t id
Definition: graphics.cc:11587
virtual void draw_pixels(int w, int h, const float *data)
Definition: gl-render.cc:3501
double get_screen_resolution(void) const
Definition: graphics.h:2208
uint8NDArray uint8_array_value(void) const
Definition: ov.h:896
std::string get_linestyle(void) const
Definition: graphics.h:10413
std::string get_marker(void) const
Definition: graphics.h:7565
void warning_with_id(const char *id, const char *fmt,...)
Definition: error.cc:803
bool facealpha_is_double(void) const
Definition: graphics.h:10391
Matrix get_color_rgb(void) const
Definition: graphics.h:4006
graphics_toolkit toolkit
Definition: gl-render.h:184
octave_value get_xticklabel(void) const
Definition: graphics.h:5610
bool is_empty(void) const
Definition: Array.h:575
double get_zPlaneN(void) const
Definition: graphics.h:5006
Matrix get_markeredgecolor_rgb(void) const
Definition: graphics.h:7569
Matrix get_opengl_matrix_1(void) const
Definition: graphics.h:4994
octave_value get_color_data(void) const
Definition: graphics.cc:8161
Octave interface to the compression and uncompression libraries.
Definition: aepbalance.cc:47
vertex_data(const Matrix &c, const Matrix &col, const Matrix &n, double a, float as, float ds, float ss, float se, float scr)
Definition: gl-render.cc:413
Matrix get_markeredgecolor_rgb(void) const
Definition: graphics.h:9517
Matrix get_facecolor_rgb(void) const
Definition: graphics.h:10398
bool style_is(const std::string &v) const
Definition: graphics.h:9202
void set___gl_vendor__(const octave_value &val) const
Definition: graphics.h:4598
bool linestyle_is(const std::string &v) const
Definition: graphics.h:9507
int get_zstate(void) const
Definition: graphics.h:5000
void tex_coord(double q, double r) const
Definition: gl-render.cc:169
double get_edgealpha_double(void) const
Definition: graphics.h:9466
virtual void init_marker(const std::string &m, double size, float width)
Definition: gl-render.cc:3763
bool is_visible(void) const
Definition: graphics.h:2704
void combine(GLdouble xyz[3], void *data[4], GLfloat w[4], void **out_data)
Definition: gl-render.cc:521
bool gridcolormode_is(const std::string &v) const
Definition: graphics.h:5496
Matrix get_backgroundcolor_rgb(void) const
Definition: graphics.h:12816
double get_x_max(void) const
Definition: graphics.h:5014
virtual void draw_text(const text::properties &props)
Definition: gl-render.cc:3243
Matrix get_data_position(void) const
Definition: graphics.cc:7981
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
Definition: dMatrix.h:145
octave_int< T > xmax(const octave_int< T > &x, const octave_int< T > &y)
vertex_data(const vertex_data &v)
Definition: gl-render.cc:410
bool edgealpha_is(const std::string &v) const
Definition: graphics.h:9465
texture_rep(GLuint id_arg, int w_arg, int h_arg, int tw_arg, int th_arg)
Definition: gl-render.cc:108
graphics_handle get_xlabel(void) const
Definition: graphics.h:5592
Matrix get_gridcolor_rgb(void) const
Definition: graphics.h:5493
void draw_axes_children(const axes::properties &props)
Definition: gl-render.cc:1826
bool isa(const std::string &go_name) const
Definition: graphics.h:3286
void text_to_pixels(const std::string &txt, uint8NDArray &pxls, Matrix &bbox, int halign, int valign, double rotation=0.0, const caseless_str &interpreter="tex", bool handle_rotation=true)
virtual void set_polygon_offset(bool on, float offset=0.0f)
Definition: gl-render.cc:3594
bool is_uint16_type(void) const
Definition: ov.h:650
graphics_handle get_zlabel(void) const
Definition: graphics.h:5679
bool linestyle_is(const std::string &v) const
Definition: graphics.h:7559
opengl_texture(const opengl_texture &tx)
Definition: gl-render.cc:141
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:363
bool get_nearhoriz(void) const
Definition: graphics.h:5035
octave_value get_position(void) const
Definition: graphics.h:9200
octave_value get_color(void) const
Definition: graphics.h:9198
Matrix xscale(const Matrix &m) const
Definition: graphics.h:4899
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:5068
static octave_idx_type nn
Definition: DASPK.cc:71
F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T F77_REAL F77_REAL &F77_RET_T F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE const F77_DBLE * f
virtual void text_to_strlist(const std::string &txt, std::list< text_renderer::string > &lst, Matrix &bbox, int halign=0, int valign=0, double rotation=0.0)
Definition: gl-render.cc:4101
static void tess_error(GLenum err, void *t)
Definition: gl-render.cc:348
bool ok(void) const
Return the CPU time used by your Octave session The first output is the total time spent executing your process and is equal to the sum of second and third which are the number of CPU seconds spent executing in user mode and the number of CPU seconds spent executing in system mode
Definition: data.cc:6386
virtual void draw_uibuttongroup(const uibuttongroup::properties &props, const graphics_object &go)
Definition: gl-render.cc:766
std::string get_boxstyle(void) const
Definition: graphics.h:5421
void set___gl_version__(const octave_value &val) const
Definition: graphics.h:4607
Matrix get_color_rgb(void) const
Definition: graphics.h:5453
std::list< vertex_data > tmp_vdata
Definition: gl-render.cc:583
octave_value get_zdata(void) const
Definition: graphics.h:7587
virtual void draw(const graphics_object &go, bool toplevel=true)
Definition: gl-render.cc:652
bool isnan(double x)
Definition: lo-mappers.cc:347
vertex_data_rep * get_rep(void) const
Definition: gl-render.cc:439
static void tess_end(void *t)
Definition: gl-render.cc:335
OCTAVE_EXPORT octave_value_list return the value of the option it must match the dimension of the state and the relative tolerance must also be a vector of the same length tem it must match the dimension of the state and the absolute tolerance must also be a vector of the same length The local error test applied at each integration step is xample roup so it is best to provide a consistent set and leave this option set to zero tem it may help to set this parameter to a nonzero value it is probably best to try leaving this option set to zero first
Definition: DASSL-opts.cc:419
void draw_axes_z_grid(const axes::properties &props)
Definition: gl-render.cc:1611
unsigned int marker_id
Definition: gl-render.h:198
std::string get_minorgridlinestyle(void) const
Definition: graphics.h:5527
void draw_all_lights(const base_properties &props, std::list< graphics_object > &obj_list)
Definition: gl-render.cc:1780
for large enough k
Definition: lu.cc:606
double get_z_max(void) const
Definition: graphics.h:5018
octave_value get_faces(void) const
Definition: graphics.h:9498
double get_fy(void) const
Definition: graphics.h:5020
bool markerfacecolor_is(const std::string &v) const
Definition: graphics.h:9521
octave_refcount< int > count
Definition: gl-render.cc:130
virtual std::string graphics_object_name(void) const
Definition: graphics.h:2431
bool edgelighting_is(const std::string &v) const
Definition: graphics.h:10385
void end_polygon(void) const
Definition: gl-render.cc:284
void error(const char *fmt,...)
Definition: error.cc:570
std::string get_gridlinestyle(void) const
Definition: graphics.h:5500
virtual void draw_image(const image::properties &props)
Definition: gl-render.cc:3281
Matrix zscale(const Matrix &m) const
Definition: graphics.h:4901
bool linestyle_is(const std::string &v) const
Definition: graphics.h:10412
double get_linewidth(void) const
Definition: graphics.h:5511
virtual void error(GLenum err)
Definition: gl-render.cc:308
bool backfacelighting_is(const std::string &v) const
Definition: graphics.h:9452
double get_diffusestrength(void) const
Definition: graphics.h:10371
virtual void init_gl_context(bool enhanced, const Matrix &backgroundColor)
Definition: gl-render.cc:784
vertex_data(vertex_data_rep *new_rep)
Definition: gl-render.cc:419
double get_ambientstrength(void) const
Definition: graphics.h:9450
octave_value get_xdata(void) const
Definition: graphics.h:8724
virtual void setup_opengl_transformation(const axes::properties &props)
Definition: gl-render.cc:1094
void set___gl_extensions__(const octave_value &val) const
Definition: graphics.h:4580
octave_value get_ymtick(void) const
Definition: graphics.h:5726
virtual void render_grid(const double linewidth, const std::string &gridstyle, const Matrix &gridcolor, const double gridalpha, const Matrix &ticks, double lim1, double lim2, double p1, double p1N, double p2, double p2N, int xyz, bool is_3D)
Definition: gl-render.cc:855
bool has_property(const caseless_str &pname) const
double get_markersize(void) const
Definition: graphics.h:9525
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function t
Definition: ov-usr-fcn.cc:935
bool facecolor_is(const std::string &v) const
Definition: graphics.h:10397
bool markeredgecolor_is(const std::string &v) const
Definition: graphics.h:10421
octave_value get_ytick(void) const
Definition: graphics.h:5653
std::string get_marker(void) const
Definition: graphics.h:9513
bool edgecolor_is(const std::string &v) const
Definition: graphics.h:10381
octave_value get_xmtick(void) const
Definition: graphics.h:5724
s
Definition: file-io.cc:2682
void bind(int mode) const
Definition: gl-render.cc:119
double get_xticklen(void) const
Definition: graphics.h:5022
double get_facealpha_double(void) const
Definition: graphics.h:10393
bool is_zminortick(void) const
Definition: graphics.h:5689
virtual void combine(GLdouble[3], void *[4], GLfloat[4], void **)
Definition: gl-render.cc:303
Matrix get_edgecolor_rgb(void) const
Definition: graphics.h:10382
std::string get_tag(void) const
Definition: graphics.h:2696
Matrix yscale(const Matrix &m) const
Definition: graphics.h:4900
static void tess_begin(GLenum type, void *t)
Definition: gl-render.cc:332
bool markerfacecolor_is(const std::string &v) const
Definition: graphics.h:10426
virtual Matrix render_text(const std::string &txt, double x, double y, double z, int halign, int valign, double rotation=0.0)
Definition: gl-render.cc:4111
std::string get_ticklabelinterpreter(void) const
Definition: graphics.h:5557
Matrix get_markerfacecolor_rgb(void) const
Definition: graphics.h:9522
octave_idx_type rows(void) const
Definition: Array.h:401
octave_value get(bool all=false) const
Definition: graphics.h:3211
octave_function * fcn
Definition: ov-class.cc:1743
double get_xpTickN(void) const
Definition: graphics.h:5008
F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T F77_REAL F77_REAL &F77_RET_T F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
graphics_xform get_transform(void) const
Definition: graphics.h:4989
octave_value get_xdata(void) const
Definition: graphics.h:10446
void add_vertex(double *loc, void *data) const
Definition: gl-render.cc:293
vertex_data_rep * rep
Definition: gl-render.cc:397
bool zcolormode_is(const std::string &v) const
Definition: graphics.h:5670
virtual void init(void)
Definition: gl-render.cc:311
octave_refcount< int > count
Definition: gl-render.cc:381
calling an anonymous function involves an overhead quite comparable to the overhead of an m file function Passing a handle to a built in function is because the interpreter is not involved in the internal loop For a
Definition: cellfun.cc:398
octave_value get_ydata(void) const
Definition: graphics.h:8726
double get_edgealpha_double(void) const
Definition: graphics.h:10377
bool color_is(const std::string &v) const
Definition: graphics.h:7547
bool swap
Definition: load-save.cc:725
double get_specularexponent(void) const
Definition: graphics.h:9529
double get_diffusestrength(void) const
Definition: graphics.h:9460
bool marker_is(const std::string &v) const
Definition: graphics.h:9512
bool edgealpha_is_double(void) const
Definition: graphics.h:9464
static int next_power_of_2(int n)
Definition: gl-render.cc:46
bool edgecolor_is(const std::string &v) const
Definition: graphics.h:9470
virtual void draw_axes(const axes::properties &props)
Definition: gl-render.cc:1914
octave_uint8 clip_code(double x, double y, double z) const
Definition: gl-render.h:154
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:439
double get_zpTickN(void) const
Definition: graphics.h:5012
bool get_xyzSym(void) const
Definition: graphics.h:5033
double h
Definition: graphics.cc:11205
Matrix scale(const Matrix &m) const
Definition: graphics.h:4903
FloatNDArray float_array_value(bool frc_str_conv=false) const
Definition: ov.h:796
void tex_coord(double q, double r) const
Definition: gl-render.cc:122
double get_specularstrength(void) const
Definition: graphics.h:10439
virtual void vertex(void *)
Definition: gl-render.cc:301
Matrix get_markerfacecolor_rgb(void) const
Definition: graphics.h:7574
double get_minorgridalpha(void) const
Definition: graphics.h:5513
virtual void set_clipping(bool on)
Definition: gl-render.cc:3734
Matrix get_children(void) const
Definition: graphics.h:2517
void begin_polygon(bool filled=true)
Definition: gl-render.cc:276
text_renderer txt_renderer
Definition: gl-render.h:206
virtual void draw_line(const line::properties &props)
Definition: gl-render.cc:1983
Matrix get_ycolor_rgb(void) const
Definition: graphics.h:5625
Matrix get_ambientlightcolor_rgb(void) const
Definition: graphics.h:5414
octave_value get_zticklabel(void) const
Definition: graphics.h:5697
std::string string_value(bool force=false) const
Definition: ov.h:908
#define loc(X, Y)
Definition: Screen.cpp:56
static void tess_combine(GLdouble c[3], void *v[4], GLfloat w[4], void **out, void *t)
Definition: gl-render.cc:341
void text_to_strlist(const std::string &txt, std::list< string > &lst, Matrix &box, int halign, int valign, double rotation=0.0, const caseless_str &interpreter="tex")
nd deftypefn *octave_map m
Definition: ov-struct.cc:2058
double get_markersize(void) const
Definition: graphics.h:7577
opengl_texture(texture_rep *_rep)
Definition: gl-render.cc:136
bool is_filled(void) const
Definition: gl-render.cc:329
void set_font(const std::string &name, const std::string &weight, const std::string &angle, double size)
int get_ystate(void) const
Definition: graphics.h:4999
virtual void draw_hggroup(const hggroup::properties &props)
Definition: gl-render.cc:3237
std::complex< double > w(std::complex< double > z, double relerr=0)
double get_fx(void) const
Definition: graphics.h:5019
Matrix get_extent_matrix(void) const
Definition: graphics.cc:7992
Matrix get_zcolor_rgb(void) const
Definition: graphics.h:5667
double get_yPlane(void) const
Definition: graphics.h:5003
octave_value get_zmtick(void) const
Definition: graphics.h:5728
vertex_data_rep(const Matrix &c, const Matrix &col, const Matrix &n, double a, float as, float ds, float ss, float se, float scr)
Definition: gl-render.cc:388
void set___gl_renderer__(const octave_value &val) const
Definition: graphics.h:4589
double signum(double x)
Definition: lo-mappers.h:259
double get_specularcolorreflectance(void) const
Definition: graphics.h:9527
octave_value get_ydata(void) const
Definition: graphics.h:7583
double get_ypTickN(void) const
Definition: graphics.h:5010
bool facealpha_is(const std::string &v) const
Definition: graphics.h:9481
bool facealpha_is(const std::string &v) const
Definition: graphics.h:10392
bool is_double_type(void) const
Definition: ov.h:624
octave_value get_vertexnormals(void) const
Definition: graphics.h:9533
bool is_valid(void) const
Definition: gl-render.cc:172
std::string get_box(void) const
Definition: graphics.h:5418
const T * data(void) const
Definition: Array.h:582
bool get_y2Dright(void) const
Definition: graphics.h:5029
virtual void draw_marker(double x, double y, double z, const Matrix &lc, const Matrix &fc)
Definition: gl-render.cc:3827
Matrix get_edgecolor_rgb(void) const
Definition: graphics.h:9471
bool edgecolor_is_rgb(void) const
Definition: graphics.h:10380
double tmp
Definition: data.cc:6300
is false
Definition: cellfun.cc:398
double get_specularstrength(void) const
Definition: graphics.h:9531
bool markeredgecolor_is(const std::string &v) const
Definition: graphics.h:9516
octave_value retval
Definition: data.cc:6294
Matrix get_backgroundcolor_rgb(void) const
Definition: graphics.h:12415
void set_color(const Matrix &c)
#define panic_impossible()
Definition: error.h:40
virtual void set_linewidth(float w)
Definition: gl-render.cc:3624
virtual void end_marker(void)
Definition: gl-render.cc:3803
std::string get_linestyle(void) const
Definition: graphics.h:9508
bool finite(double x)
Definition: lo-mappers.cc:367
double get_y_max(void) const
Definition: graphics.h:5016
base_properties & get_properties(void)
Definition: graphics.h:3288
static void tess_edge_flag(GLboolean flag, void *t)
Definition: gl-render.cc:345
double get_ytickoffset(void) const
Definition: graphics.h:5026
Matrix get_color_rgb(void) const
Definition: graphics.h:7548
virtual void end(void)
Definition: gl-render.cc:299
double get_xPlaneN(void) const
Definition: graphics.h:5002
idx type
Definition: ov.cc:3129
std::string get_marker(void) const
Definition: graphics.h:10418
virtual void begin(GLenum)
Definition: gl-render.cc:297
Definition: dMatrix.h:37
vertex_data_rep * nil_rep(void) const
Definition: gl-render.cc:399
static int get_maxlights(void)
Definition: gl-render.cc:601
sz
Definition: data.cc:5342
bool get_layer2Dtop(void) const
Definition: graphics.h:5030
the sparsity preserving column transformation such that that defines the pivoting threshold can be given in which case it defines the c
Definition: lu.cc:138
bool marker_is(const std::string &v) const
Definition: graphics.h:7564
graphics_object get_ancestor(const std::string &type) const
Definition: graphics.cc:3404
dim_vector dims(void) const
Definition: ov.h:486
octave_value get_cameraposition(void) const
Definition: graphics.h:5423
string_vector string_vector_value(bool pad=false) const
Definition: ov.h:911
Matrix matrix_value(bool frc_str_conv=false) const
Definition: ov.h:787
virtual void set_linestyle(const std::string &s, bool stipple=false, double linewidth=0.5)
Definition: gl-render.cc:3643
double get_linewidth(void) const
Definition: graphics.h:10415
Matrix get_xcolor_rgb(void) const
Definition: graphics.h:5580
octave_value get_vertices(void) const
Definition: graphics.h:9538
Definition: marker.h:39
bool is_clipping(void) const
Definition: graphics.h:2670
bool isinf(double x)
Definition: lo-mappers.cc:387
#define CALLBACK
Definition: gl-render.cc:93
double get_xPlane(void) const
Definition: graphics.h:5001
bool get_zSign(void) const
Definition: graphics.h:5034
octave_value get_string(void) const
Definition: graphics.h:8095
bool edgealpha_is(const std::string &v) const
Definition: graphics.h:10376
double get_yPlaneN(void) const
Definition: graphics.h:5004
bool is_zminorgrid(void) const
Definition: graphics.h:5686
bool edgealpha_is_double(void) const
Definition: graphics.h:10375
octave_int< T > xmin(const octave_int< T > &x, const octave_int< T > &y)
virtual void set_viewport(int w, int h)
Definition: gl-render.cc:3481
double get_ypTick(void) const
Definition: graphics.h:5009
bool xcolormode_is(const std::string &v) const
Definition: graphics.h:5583
void warning(const char *fmt,...)
Definition: error.cc:788
bool get_xySym(void) const
Definition: graphics.h:5032
virtual void set_color(const Matrix &c)
Definition: gl-render.cc:3564
bool valid_object(void) const
Definition: graphics.h:3306
bool facecolor_is_rgb(void) const
Definition: graphics.h:9485
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:228
octave_value get_ydata(void) const
Definition: graphics.h:10450
bool is_empty(void) const
Definition: ov.h:542
double get_facealpha_double(void) const
Definition: graphics.h:9482
void draw_axes_boxes(const axes::properties &props)
Definition: gl-render.cc:1205
static std::string gl_get_string(GLenum id)
Definition: gl-render.cc:713
virtual void draw_light(const light::properties &props)
Definition: gl-render.cc:3200
Matrix get_opengl_matrix_2(void) const
Definition: graphics.h:4995
NDArray array_value(bool frc_str_conv=false) const
Definition: ov.h:793
virtual octave_value get(const caseless_str &pname) const
bool is_nan_or_inf(double x, double y, double z) const
Definition: gl-render.h:146
texture_rep * rep
Definition: gl-render.cc:133
bool edgelighting_is(const std::string &v) const
Definition: graphics.h:9474
double get_xtickoffset(void) const
Definition: graphics.h:5025
unsigned int current_light
Definition: gl-render.h:210
double get_fz(void) const
Definition: graphics.h:5021
bool is_ygrid(void) const
Definition: graphics.h:5634
bool is_box(void) const
Definition: graphics.h:5417
patch_tesselator(opengl_renderer *r, int cmode, int lmode, float idx=0.0)
Definition: gl-render.cc:446
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
unsigned int filled_marker_id
Definition: gl-render.h:198
double get_yticklen(void) const
Definition: graphics.h:5023
double get_markersize(void) const
Definition: graphics.h:10430
bool is_uint8_type(void) const
Definition: ov.h:647
static opengl_texture create(const octave_value &data)
Definition: gl-render.cc:177
p
Definition: lu.cc:138
#define LIGHT_MODE
Definition: gl-render.cc:62
virtual void edge_flag(GLboolean)
Definition: gl-render.cc:306
virtual graphics_toolkit get_toolkit(void) const
Definition: graphics.cc:3128
bool is_graphicssmoothing(void) const
Definition: graphics.h:4024
int get_xstate(void) const
Definition: graphics.h:4998
static void tess_vertex(void *v, void *t)
Definition: gl-render.cc:338
double get_z_min(void) const
Definition: graphics.h:5017
virtual void render_tickmarks(const Matrix &ticks, double lim1, double lim2, double p1, double p1N, double p2, double p2N, double dx, double dy, double dz, int xyz, bool doubleside)
Definition: gl-render.cc:931
issues an error eealso double
Definition: ov-bool-mat.cc:594
virtual void text_to_pixels(const std::string &txt, uint8NDArray &pixels, Matrix &bbox, int halign=0, int valign=0, double rotation=0.0)
Definition: gl-render.cc:4091
bool is_yminorgrid(void) const
Definition: graphics.h:5644
Matrix get_all_children(void) const
Definition: graphics.h:2522
graphics_xform xform
Definition: gl-render.h:187
double get_specularexponent(void) const
Definition: graphics.h:10437
bool is_xminortick(void) const
Definition: graphics.h:5602
void begin_contour(void) const
Definition: gl-render.cc:287
Matrix get_minorgridcolor_rgb(void) const
Definition: graphics.h:5520
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:301
double get_x_min(void) const
Definition: graphics.h:5013
double get_y_min(void) const
Definition: graphics.h:5015
the element is set to zero In other the statement xample y
Definition: data.cc:5342
virtual void draw_uipanel(const uipanel::properties &props, const graphics_object &go)
Definition: gl-render.cc:748
double get_xpTick(void) const
Definition: graphics.h:5007
bool facealpha_is_double(void) const
Definition: graphics.h:9480
b
Definition: cellfun.cc:398
double get_gridalpha(void) const
Definition: graphics.h:5486
bool backfacelighting_is(const std::string &v) const
Definition: graphics.h:10361
bool ycolormode_is(const std::string &v) const
Definition: graphics.h:5628
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:200
static graphics_object get_object(double val)
Definition: graphics.h:13794
bool is_xminorgrid(void) const
Definition: graphics.h:5599
bool get_is2D(void) const
Definition: graphics.h:5031
double get_zpTick(void) const
Definition: graphics.h:5011
double get_specularcolorreflectance(void) const
Definition: graphics.h:10435
double get_linewidth(void) const
Definition: graphics.h:7562
double get_ambientstrength(void) const
Definition: graphics.h:10359
unsigned int make_marker_list(const std::string &m, double size, bool filled) const
Definition: gl-render.cc:3910
virtual void draw_patch(const patch::properties &props)
Definition: gl-render.cc:2732
Matrix get_markeredgecolor_rgb(void) const
Definition: graphics.h:10422
octave_value get_ztick(void) const
Definition: graphics.h:5695
virtual ~opengl_tesselator(void)
Definition: gl-render.cc:273
void bind(int mode=GL_TEXTURE_2D) const
Definition: gl-render.cc:166
octave_value get_color_data(void) const
Definition: graphics.cc:8169
void draw_axes_x_grid(const axes::properties &props)
Definition: gl-render.cc:1339
double get_zticklen(void) const
Definition: graphics.h:5024
OCTAVE_EXPORT octave_value_list error nd deftypefn *const octave_scalar_map err
Definition: error.cc:1036
OCTAVE_EXPORT octave_value_list any number nd example oindent prints the prompt xample Pick a any number!nd example oindent and waits for the user to enter a value The string entered by the user is evaluated as an so it may be a literal a variable or any other valid Octave code The number of return their size
Definition: input.cc:871
octave_value get_vertexnormals(void) const
Definition: graphics.h:10441
bool facecolor_is(const std::string &v) const
Definition: graphics.h:9486
virtual void draw_surface(const surface::properties &props)
Definition: gl-render.cc:2120
octave_value get_color_data(void) const
Definition: graphics.cc:8369
octave_value get_xdata(void) const
Definition: graphics.h:7579
const T * fortran_vec(void) const
Definition: Array.h:584
virtual void finish(void)
Definition: gl-render.cc:1077
bool is_single_type(void) const
Definition: ov.h:627
bool minorgridcolormode_is(const std::string &v) const
Definition: graphics.h:5523
bool marker_is(const std::string &v) const
Definition: graphics.h:10417
Matrix get_markerfacecolor_rgb(void) const
Definition: graphics.h:10427
ColumnVector transform(double x, double y, double z, bool use_scale=true) const
Definition: graphics.cc:6622
double double_value(bool frc_str_conv=false) const
Definition: ov.h:775
bool edgecolor_is_rgb(void) const
Definition: graphics.h:9469
bool markerfacecolor_is(const std::string &v) const
Definition: graphics.h:7573
virtual void draw_figure(const figure::properties &props)
Definition: gl-render.cc:727
double get_linewidth(void) const
Definition: graphics.h:9510
bool facelighting_is(const std::string &v) const
Definition: graphics.h:10401
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
GLUtesselator * glu_tess
Definition: gl-render.cc:359
Matrix get_transform_zlim(void) const
Definition: graphics.h:4996
virtual void set_interpreter(const caseless_str &interp)
Definition: gl-render.h:89
bool is_yminortick(void) const
Definition: graphics.h:5647
bool markeredgecolor_is(const std::string &v) const
Definition: graphics.h:7568
bool meshstyle_is(const std::string &v) const
Definition: graphics.h:10432
virtual void set_clipbox(double x1, double x2, double y1, double y2, double z1, double z2)
Definition: gl-render.cc:3684
virtual void set_font(const base_properties &props)
Definition: gl-render.cc:3585
void err_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
Definition: errwarn.cc:50
set(hf,"paperorientation") esult
Definition: graphics.cc:10111
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:854
virtual void render_ticktexts(const Matrix &ticks, const string_vector &ticklabels, double lim1, double lim2, double p1, double p2, int xyz, int ha, int va, int &wmax, int &hmax)
Definition: gl-render.cc:1007
const uint8NDArray & get_pixels(void) const
Definition: graphics.h:8500
dim_vector dv
Definition: sub2ind.cc:263
uint16NDArray uint16_array_value(void) const
Definition: ov.h:899
bool is_zgrid(void) const
Definition: graphics.h:5676
void end_contour(void) const
Definition: gl-render.cc:290
octave_idx_type columns(void) const
Definition: Array.h:410
double get_ztickoffset(void) const
Definition: graphics.h:5027
octave_value get_zdata(void) const
Definition: graphics.h:10454
bool has_bad_data(std::string &msg) const
Definition: graphics.h:9281
ColumnVector view_vector
Definition: gl-render.h:201
void xform(ColumnVector &v, const Matrix &m)
Definition: graphics.cc:5162
bool facecolor_is_rgb(void) const
Definition: graphics.h:10396
double get_zPlane(void) const
Definition: graphics.h:5005
bool facelighting_is(const std::string &v) const
Definition: graphics.h:9490
std::string get_linestyle(void) const
Definition: graphics.h:7560
graphics_handle get_ylabel(void) const
Definition: graphics.h:5637
void set_normal(int bfl_mode, const NDArray &n, int j, int i)
Definition: gl-render.cc:3876
F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T F77_REAL F77_REAL &F77_RET_T F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE * x
void draw_axes_planes(const axes::properties &props)
Definition: gl-render.cc:1145
void draw_axes_y_grid(const axes::properties &props)
Definition: gl-render.cc:1476
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:205
bool get_x2Dtop(void) const
Definition: graphics.h:5028
Matrix get_facecolor_rgb(void) const
Definition: graphics.h:9487
octave_value get_yticklabel(void) const
Definition: graphics.h:5655
octave_value get_xtick(void) const
Definition: graphics.h:5608
bool is_xgrid(void) const
Definition: graphics.h:5589