[Pkg-octave-commit] r2347 - in octave/trunk/debian: . patches
Rafael Laboissiere
rafael at alioth.debian.org
Tue Jul 22 20:54:40 UTC 2008
Author: rafael
Date: 2008-07-22 20:54:40 +0000 (Tue, 22 Jul 2008)
New Revision: 2347
Removed:
octave/trunk/debian/patches/add-gl-render-cc.dpatch
Modified:
octave/trunk/debian/changelog
Log:
Drop patch
Modified: octave/trunk/debian/changelog
===================================================================
--- octave/trunk/debian/changelog 2008-07-22 20:13:15 UTC (rev 2346)
+++ octave/trunk/debian/changelog 2008-07-22 20:54:40 UTC (rev 2347)
@@ -5,10 +5,11 @@
+ Do not install octave.st for octave3.1 (avoid conflict with
octave3.0)
+ Set alternatives priority value for octave3.1
- * debian/patches/fix-comma-in-configure.dpatch: Drop patch (applied
- upstream)
+ * Drop patch (applied upstream):
+ + fix-comma-in-configure.dpatch
+ + add-gl-render-cc.dpatch
- -- Rafael Laboissiere <rafael at debian.org> Tue, 22 Jul 2008 17:30:55 +0200
+ -- Rafael Laboissiere <rafael at debian.org> Tue, 22 Jul 2008 22:13:35 +0200
octave3.1 (3.1.50-2) experimental; urgency=low
Deleted: octave/trunk/debian/patches/add-gl-render-cc.dpatch
===================================================================
--- octave/trunk/debian/patches/add-gl-render-cc.dpatch 2008-07-22 20:13:15 UTC (rev 2346)
+++ octave/trunk/debian/patches/add-gl-render-cc.dpatch 2008-07-22 20:54:40 UTC (rev 2347)
@@ -1,2828 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## -*- diff -*-
-## add-gl-render-cc.dpatch by Rafael Laboissiere <rafael at debian.org>
-##
-## DP: Add src/gl-render.cc, which is lacking in the 3.1.50 tarball
-
- at DPATCH@
-
---- octave3.1-3.1.50.orig/src/gl-render.cc
-+++ octave3.1-3.1.50/src/gl-render.cc
-@@ -0,0 +1,2817 @@
-+/*
-+
-+Copyright (C) 2008 Michael Goffioul
-+
-+This file is part of Octave.
-+
-+Octave is free software; you can redistribute it and/or modify it
-+under the terms of the GNU General Public License as published by the
-+Free Software Foundation; either version 3 of the License, or (at your
-+option) any later version.
-+
-+Octave is distributed in the hope that it will be useful, but WITHOUT
-+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-+for more details.
-+
-+You should have received a copy of the GNU General Public License
-+along with Octave; see the file COPYING. If not, see
-+<http://www.gnu.org/licenses/>.
-+
-+*/
-+
-+#ifdef HAVE_CONFIG_H
-+#include <config.h>
-+#endif
-+
-+#include <lo-mappers.h>
-+#include "gl-render.h"
-+
-+#define LIGHT_MODE GL_FRONT_AND_BACK
-+
-+// Win32 API requires the CALLBACK attributes for
-+// GLU callback functions. Define it to empty on
-+// other platforms.
-+#ifndef CALLBACK
-+#define CALLBACK
-+#endif
-+
-+enum {
-+ AXE_ANY_DIR = 0,
-+ AXE_DEPTH_DIR = 1,
-+ AXE_HORZ_DIR = 2,
-+ AXE_VERT_DIR = 3
-+};
-+
-+static octave_idx_type
-+xmin (octave_idx_type x, octave_idx_type y)
-+{
-+ return x < y ? x : y;
-+}
-+
-+class
-+opengl_texture
-+{
-+protected:
-+ class texture_rep
-+ {
-+ public:
-+ texture_rep (void) : valid (false), count (1) { }
-+
-+ texture_rep (GLuint _id, int _w, int _h, int _tw, int _th)
-+ : id (_id), w (_w), h (_h), tw (_tw), th (_th),
-+ tx (double(w)/tw), ty (double(h)/th), valid (true),
-+ count (1) { }
-+
-+ ~texture_rep (void)
-+ {
-+ if (valid)
-+ glDeleteTextures (1, &id);
-+ }
-+
-+ void bind (int mode) const
-+ { if (valid) glBindTexture (mode, id); }
-+
-+ void tex_coord (double q, double r) const
-+ { if (valid) glTexCoord2d (q*tx, r*ty); }
-+
-+ GLuint id;
-+ int w, h;
-+ int tw, th;
-+ double tx, ty;
-+ bool valid;
-+ int count;
-+ };
-+
-+ texture_rep *rep;
-+
-+private:
-+ opengl_texture (texture_rep *_rep) : rep (_rep) { }
-+
-+public:
-+ opengl_texture (void) : rep (new texture_rep ()) { }
-+
-+ opengl_texture (const opengl_texture& tx)
-+ : rep (tx.rep)
-+ {
-+ rep->count++;
-+ }
-+
-+ ~opengl_texture (void)
-+ {
-+ if (--rep->count == 0)
-+ delete rep;
-+ }
-+
-+ opengl_texture& operator = (const opengl_texture& tx)
-+ {
-+ if (--rep->count == 0)
-+ delete rep;
-+
-+ rep = tx.rep;
-+ rep->count++;
-+
-+ return *this;
-+ }
-+
-+ static opengl_texture create (const octave_value& data);
-+
-+ void bind (int mode = GL_TEXTURE_2D) const
-+ { rep->bind (mode); }
-+
-+ void tex_coord (double q, double r) const
-+ { rep->tex_coord (q, r); }
-+
-+ bool is_valid (void) const
-+ { return rep->valid; }
-+};
-+
-+static int
-+next_power_of_2 (int n)
-+{
-+ int m = 1;
-+
-+ while (m < n && m < INT_MAX)
-+ m <<= 1;
-+
-+ return m;
-+}
-+
-+opengl_texture
-+opengl_texture::create (const octave_value& data)
-+{
-+ opengl_texture retval;
-+
-+ dim_vector dv (data.dims ());
-+
-+ // Expect RGB data
-+ if (dv.length () == 3 && dv(2) == 3)
-+ {
-+ int h = dv(0), w = dv(1), tw, th;
-+ GLuint id;
-+ bool ok = true;
-+
-+ tw = next_power_of_2 (w);
-+ th = next_power_of_2 (w);
-+
-+ glGenTextures (1, &id);
-+ glBindTexture (GL_TEXTURE_2D, id);
-+
-+ if (data.is_double_type ())
-+ {
-+ NDArray _a = data.array_value ();
-+
-+ OCTAVE_LOCAL_BUFFER (float, a, (3*tw*th));
-+
-+ for (int i = 0; i < h; i++)
-+ for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3)
-+ {
-+ a[idx] = _a(i,j,0);
-+ a[idx+1] = _a(i,j,1);
-+ a[idx+2] = _a(i,j,2);
-+ }
-+
-+ glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0,
-+ GL_RGB, GL_FLOAT, a);
-+ }
-+ else if (data.is_uint8_type ())
-+ {
-+ uint8NDArray _a = data.uint8_array_value ();
-+
-+ OCTAVE_LOCAL_BUFFER (octave_uint8, a, (3*tw*th));
-+
-+ for (int i = 0; i < h; i++)
-+ for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3)
-+ {
-+ a[idx] = _a(i,j,0);
-+ a[idx+1] = _a(i,j,1);
-+ a[idx+2] = _a(i,j,2);
-+ }
-+
-+ glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0,
-+ GL_RGB, GL_UNSIGNED_BYTE, a);
-+ }
-+ else
-+ {
-+ ok = false;
-+ warning ("opengl_texture::create: invalid texture data type (expected double or uint8)");
-+ }
-+
-+ if (ok)
-+ {
-+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-+
-+ if (glGetError () != GL_NO_ERROR)
-+ warning ("opengl_texture::create: OpenGL error while generating texture data");
-+ else
-+ retval = opengl_texture (new texture_rep (id, w, h, tw, th));
-+ }
-+ }
-+ else
-+ warning ("opengl_texture::create: invalid texture data size");
-+
-+ return retval;
-+}
-+
-+class
-+opengl_tesselator
-+{
-+public:
-+ typedef void (CALLBACK *fcn) (void);
-+
-+public:
-+
-+ opengl_tesselator (void) : glu_tess (0) { init (); }
-+
-+ virtual ~opengl_tesselator (void)
-+ { if (glu_tess) gluDeleteTess (glu_tess); }
-+
-+ void begin_polygon (bool filled = true)
-+ {
-+ gluTessProperty (glu_tess, GLU_TESS_BOUNDARY_ONLY,
-+ (filled ? GL_FALSE : GL_TRUE));
-+ fill = filled;
-+ gluTessBeginPolygon (glu_tess, this);
-+ }
-+
-+ void end_polygon (void) const
-+ { gluTessEndPolygon (glu_tess); }
-+
-+ void begin_contour (void) const
-+ { gluTessBeginContour (glu_tess); }
-+
-+ void end_contour (void) const
-+ { gluTessEndContour (glu_tess); }
-+
-+ void add_vertex (double *loc, void *data) const
-+ { gluTessVertex (glu_tess, loc, data); }
-+
-+protected:
-+ virtual void begin (GLenum /*type*/) { }
-+
-+ virtual void end (void) { }
-+
-+ virtual void vertex (void */*data*/) { }
-+
-+ virtual void combine (GLdouble /*c*/[3], void */*data*/[4],
-+ GLfloat /*w*/[4], void **/*out_data*/) { }
-+
-+ virtual void edge_flag (GLboolean /*flag*/) { }
-+
-+ virtual void error (GLenum err)
-+ { ::error ("OpenGL tesselation error (%d)", err); }
-+
-+ virtual void init (void)
-+ {
-+ glu_tess = gluNewTess ();
-+
-+ gluTessCallback (glu_tess, GLU_TESS_BEGIN_DATA,
-+ reinterpret_cast<fcn> (tess_begin));
-+ gluTessCallback (glu_tess, GLU_TESS_END_DATA,
-+ reinterpret_cast<fcn> (tess_end));
-+ gluTessCallback (glu_tess, GLU_TESS_VERTEX_DATA,
-+ reinterpret_cast<fcn> (tess_vertex));
-+ gluTessCallback (glu_tess, GLU_TESS_COMBINE_DATA,
-+ reinterpret_cast<fcn> (tess_combine));
-+ gluTessCallback (glu_tess, GLU_TESS_EDGE_FLAG_DATA,
-+ reinterpret_cast<fcn> (tess_edge_flag));
-+ gluTessCallback (glu_tess, GLU_TESS_ERROR_DATA,
-+ reinterpret_cast<fcn> (tess_error));
-+ }
-+
-+ bool is_filled (void) const { return fill; }
-+
-+private:
-+ static void CALLBACK tess_begin (GLenum type, void *t)
-+ { reinterpret_cast<opengl_tesselator *> (t)->begin (type); }
-+
-+ static void CALLBACK tess_end (void *t)
-+ { reinterpret_cast<opengl_tesselator *> (t)->end (); }
-+
-+ static void CALLBACK tess_vertex (void *v, void *t)
-+ { reinterpret_cast<opengl_tesselator *> (t)->vertex (v); }
-+
-+ static void CALLBACK tess_combine (GLdouble c[3], void *v[4], GLfloat w[4],
-+ void **out, void *t)
-+ { reinterpret_cast<opengl_tesselator *> (t)->combine (c, v, w, out); }
-+
-+ static void CALLBACK tess_edge_flag (GLboolean flag, void *t)
-+ { reinterpret_cast<opengl_tesselator *> (t)->edge_flag (flag); }
-+
-+ static void CALLBACK tess_error (GLenum err, void *t)
-+ { reinterpret_cast<opengl_tesselator *> (t)->error (err); }
-+
-+private:
-+ GLUtesselator *glu_tess;
-+ bool fill;
-+};
-+
-+class
-+vertex_data
-+{
-+public:
-+ class vertex_data_rep
-+ {
-+ public:
-+ Matrix coords;
-+ Matrix color;
-+ Matrix normal;
-+ double alpha;
-+ float ambient;
-+ float diffuse;
-+ float specular;
-+ float specular_exp;
-+
-+ // reference counter
-+ int count;
-+
-+ vertex_data_rep (void) : count (1) { }
-+
-+ vertex_data_rep (const Matrix& c, const Matrix& col, const Matrix& n,
-+ double a, float as, float ds, float ss, float se)
-+ : coords (c), color (col), normal (n), alpha (a),
-+ ambient (as), diffuse (ds), specular (ss), specular_exp (se),
-+ count (1) { }
-+ };
-+
-+private:
-+ vertex_data_rep *rep;
-+
-+ vertex_data_rep *nil_rep (void) const
-+ {
-+ static vertex_data_rep *nr = new vertex_data_rep ();
-+
-+ return nr;
-+ }
-+
-+public:
-+ vertex_data (void) : rep (nil_rep ())
-+ { rep->count++; }
-+
-+ vertex_data (const vertex_data& v) : rep (v.rep)
-+ { rep->count++; }
-+
-+ vertex_data (const Matrix& c, const Matrix& col, const Matrix& n,
-+ double a, float as, float ds, float ss, float se)
-+ : rep (new vertex_data_rep (c, col, n, a, as, ds, ss, se))
-+ { }
-+
-+ vertex_data (vertex_data_rep *new_rep)
-+ : rep (new_rep) { }
-+
-+ ~vertex_data (void)
-+ {
-+ if (--rep->count == 0)
-+ delete rep;
-+ }
-+
-+ vertex_data& operator = (const vertex_data& v)
-+ {
-+ if (--rep->count == 0)
-+ delete rep;
-+
-+ rep = v.rep;
-+ rep->count++;
-+
-+ return *this;
-+ }
-+
-+ vertex_data_rep *get_rep (void) const { return rep; }
-+};
-+
-+class
-+opengl_renderer::patch_tesselator : public opengl_tesselator
-+{
-+public:
-+ patch_tesselator (opengl_renderer *r, int cmode, int lmode, int idx = 0)
-+ : opengl_tesselator (), renderer (r),
-+ color_mode (cmode), light_mode (lmode), index (idx),
-+ first (true) { }
-+
-+protected:
-+ void begin (GLenum type)
-+ {
-+ //printf("patch_tesselator::begin (%d)\n", type);
-+ first = true;
-+
-+ if (color_mode == 2 || light_mode == 2)
-+ glShadeModel (GL_SMOOTH);
-+ else
-+ glShadeModel (GL_FLAT);
-+
-+ if (is_filled ())
-+ renderer->set_polygon_offset (true, 1+index);
-+
-+ glBegin (type);
-+ }
-+
-+ void end (void)
-+ {
-+ //printf("patch_tesselator::end\n");
-+ glEnd ();
-+ renderer->set_polygon_offset (false);
-+ }
-+
-+ void vertex (void *data)
-+ {
-+ vertex_data::vertex_data_rep *v
-+ = reinterpret_cast<vertex_data::vertex_data_rep *> (data);
-+ //printf("patch_tesselator::vertex (%g, %g, %g)\n", v->coords(0), v->coords(1), v->coords(2));
-+
-+ // FIXME: why did I need to keep the first vertex of the face
-+ // in JHandles? I think it's related to the fact that the
-+ // tessellation process might re-order the vertices, such that
-+ // the first one you get here might not be the first one of the face;
-+ // but I can't figure out the actual reason.
-+ if (color_mode > 0 && (first || color_mode == 2))
-+ {
-+ Matrix col = v->color;
-+
-+ if (col.numel () == 3)
-+ {
-+ glColor3dv (col.data ());
-+ if (light_mode > 0)
-+ {
-+ float buf[4] = { 0, 0, 0, 1 };
-+
-+ for (int k = 0; k < 3; k++)
-+ buf[k] = (v->ambient * col(k));
-+ glMaterialfv (LIGHT_MODE, GL_AMBIENT, buf);
-+
-+ for (int k = 0; k < 3; k++)
-+ buf[k] = (v->diffuse * col(k));
-+ glMaterialfv (LIGHT_MODE, GL_AMBIENT, buf);
-+ }
-+ }
-+ }
-+
-+ if (light_mode > 0 && (first || light_mode == 2))
-+ glNormal3dv (v->normal.data ());
-+
-+ glVertex3dv (v->coords.data ());
-+
-+ first = false;
-+ }
-+
-+ void combine (GLdouble xyz[3], void *data[4], GLfloat w[4],
-+ void **out_data)
-+ {
-+ //printf("patch_tesselator::combine\n");
-+
-+ vertex_data::vertex_data_rep *v[4];
-+ int vmax = 4;
-+
-+ for (int i = 0; i < 4; i++)
-+ {
-+ v[i] = reinterpret_cast<vertex_data::vertex_data_rep *> (data[i]);
-+
-+ if (vmax == 4 && ! v[i])
-+ vmax = i;
-+ }
-+
-+ Matrix vv (1, 3, 0.0);
-+ Matrix cc;
-+ Matrix nn (1, 3, 0.0);
-+ double aa = 0.0;
-+
-+ vv(0) = xyz[0];
-+ vv(1) = xyz[1];
-+ vv(2) = xyz[2];
-+
-+ if (v[0]->color.numel ())
-+ {
-+ cc.resize (1, 3, 0.0);
-+ for (int ic = 0; ic < 3; ic++)
-+ for (int iv = 0; iv < vmax; iv++)
-+ cc(ic) += (w[iv] * v[iv]->color(ic));
-+ }
-+
-+ if (v[0]->normal.numel () > 0)
-+ {
-+ for (int in = 0; in < 3; in++)
-+ for (int iv = 0; iv < vmax; iv++)
-+ nn(in) += (w[iv] * v[iv]->normal(in));
-+ }
-+
-+ for (int iv = 0; iv < vmax; iv++)
-+ aa += (w[iv] * v[iv]->alpha);
-+
-+ vertex_data new_v (vv, cc, nn, aa, v[0]->ambient, v[0]->diffuse,
-+ v[0]->specular, v[0]->specular_exp);
-+ tmp_vdata.push_back (new_v);
-+
-+ *out_data = new_v.get_rep ();
-+ }
-+
-+private:
-+ opengl_renderer *renderer;
-+ int color_mode; // 0: uni, 1: flat, 2: interp
-+ int light_mode; // 0: none, 1: flat, 2: gouraud
-+ int index;
-+ bool first;
-+ std::list<vertex_data> tmp_vdata;
-+};
-+
-+void
-+opengl_renderer::draw (const graphics_object& go)
-+{
-+ if (! go.valid_object ())
-+ return;
-+
-+ const base_properties& props = go.get_properties ();
-+
-+ if (go.isa ("figure"))
-+ draw (dynamic_cast<const figure::properties&> (props));
-+ else if (go.isa ("axes"))
-+ draw (dynamic_cast<const axes::properties&> (props));
-+ else if (go.isa ("line"))
-+ draw (dynamic_cast<const line::properties&> (props));
-+ else if (go.isa ("surface"))
-+ draw (dynamic_cast<const surface::properties&> (props));
-+ else if (go.isa ("patch"))
-+ draw (dynamic_cast<const patch::properties&> (props));
-+ else if (go.isa ("hggroup"))
-+ draw (dynamic_cast<const hggroup::properties&> (props));
-+ else
-+ warning ("opengl_renderer: cannot render object of type `%s'",
-+ props.graphics_object_name ().c_str ());
-+}
-+
-+void
-+opengl_renderer::draw (const figure::properties& props)
-+{
-+ backend = props.get_backend ();
-+
-+ // Initialize OpenGL context
-+
-+ glEnable (GL_DEPTH_TEST);
-+ glDepthFunc (GL_LEQUAL);
-+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-+ glEnable (GL_NORMALIZE);
-+
-+ if (props.is___enhanced__ ())
-+ {
-+ glEnable (GL_BLEND);
-+ glEnable (GL_LINE_SMOOTH);
-+ }
-+ else
-+ {
-+ glDisable (GL_BLEND);
-+ glDisable (GL_LINE_SMOOTH);
-+ }
-+
-+ // Clear background
-+
-+ Matrix c = props.get_color_rgb ();
-+
-+ if (c.length() >= 3)
-+ {
-+ glClearColor (c(0), c(1), c(2), 1);
-+ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-+ }
-+
-+ // Draw children
-+
-+ draw (props.get_children ());
-+}
-+
-+void
-+opengl_renderer::draw (const axes::properties& props)
-+{
-+ // setup OpenGL transformation
-+
-+ Matrix x_zlim = props.get_transform_zlim ();
-+ Matrix x_mat1 = props.get_opengl_matrix_1 ();
-+ Matrix x_mat2 = props.get_opengl_matrix_2 ();
-+
-+ xZ1 = x_zlim(0)-(x_zlim(1)-x_zlim(0))/2;
-+ xZ2 = x_zlim(1)+(x_zlim(1)-x_zlim(0))/2;
-+
-+ int vw[4];
-+ glGetIntegerv (GL_VIEWPORT, vw);
-+
-+ glMatrixMode (GL_MODELVIEW);
-+ glLoadIdentity ();
-+ glScaled(1, 1, -1);
-+ glMultMatrixd (x_mat1.data ());
-+ glMatrixMode (GL_PROJECTION);
-+ glLoadIdentity ();
-+ glOrtho (0, vw[2], vw[3], 0, xZ1, xZ2);
-+ glMultMatrixd (x_mat2.data ());
-+ glMatrixMode (GL_MODELVIEW);
-+
-+ glClear (GL_DEPTH_BUFFER_BIT);
-+
-+ // store axes transformation data
-+
-+ xform = props.get_transform ();
-+
-+ // draw axes object
-+
-+ GLboolean antialias;
-+ glGetBooleanv (GL_LINE_SMOOTH, &antialias);
-+ glDisable (GL_LINE_SMOOTH);
-+
-+ Matrix xlim = xform.xscale (props.get_xlim ().matrix_value ());
-+ Matrix ylim = xform.yscale (props.get_ylim ().matrix_value ());
-+ Matrix zlim = xform.zscale (props.get_zlim ().matrix_value ());
-+ double x_min = xlim(0), x_max = xlim(1);
-+ double y_min = ylim(0), y_max = ylim(1);
-+ double z_min = zlim(0), z_max = zlim(1);
-+
-+ double xd = (props.xdir_is ("normal") ? 1 : -1);
-+ double yd = (props.ydir_is ("normal") ? 1 : -1);
-+ double zd = (props.zdir_is ("normal") ? 1 : -1);
-+
-+ ColumnVector p1, p2, xv (3), yv (3), zv (3);
-+ int xstate, ystate, zstate;
-+
-+ xstate = ystate = zstate = AXE_ANY_DIR;
-+
-+ p1 = xform.transform (x_min, (y_min+y_max)/2, (z_min+z_max)/2, false);
-+ p2 = xform.transform (x_max, (y_min+y_max)/2, (z_min+z_max)/2, false);
-+ xv(0) = xround (p2(0)-p1(0));
-+ xv(1) = xround (p2(1)-p1(1));
-+ xv(2) = (p2(2)-p1(2));
-+ if (xv(0) == 0 && xv(1) == 0)
-+ xstate = AXE_DEPTH_DIR;
-+ else if (xv(2) == 0)
-+ {
-+ if (xv(0) == 0)
-+ xstate = AXE_VERT_DIR;
-+ else if (xv(1) == 0)
-+ xstate = AXE_HORZ_DIR;
-+ }
-+ double xPlane;
-+ if (xv(2) == 0)
-+ if (xv(1) == 0)
-+ xPlane = (xv(0) > 0 ? x_max : x_min);
-+ else
-+ xPlane = (xv(1) < 0 ? x_max : x_min);
-+ else
-+ xPlane = (xv(2) < 0 ? x_min : x_max);
-+ double xPlaneN = (xPlane == x_min ? x_max : x_min);
-+ double fx = (x_max-x_min)/sqrt(xv(0)*xv(0)+xv(1)*xv(1));
-+
-+ p1 = xform.transform ((x_min+x_max)/2, y_min, (z_min+z_max)/2, false);
-+ p2 = xform.transform ((x_min+x_max)/2, y_max, (z_min+z_max)/2, false);
-+ yv(0) = xround (p2(0)-p1(0));
-+ yv(1) = xround (p2(1)-p1(1));
-+ yv(2) = (p2(2)-p1(2));
-+ if (yv(0) == 0 && yv(1) == 0)
-+ ystate = AXE_DEPTH_DIR;
-+ else if (yv(2) == 0)
-+ {
-+ if (yv(0) == 0)
-+ ystate = AXE_VERT_DIR;
-+ else if (yv(1) == 0)
-+ ystate = AXE_HORZ_DIR;
-+ }
-+ double yPlane;
-+ if (yv(2) == 0)
-+ if (yv(1) == 0)
-+ yPlane = (yv(0) > 0 ? y_max : y_min);
-+ else
-+ yPlane = (yv(1) < 0 ? y_max : y_min);
-+ else
-+ yPlane = (yv(2) < 0 ? y_min : y_max);
-+ double yPlaneN = (yPlane == y_min ? y_max : y_min);
-+ double fy = (y_max-y_min)/sqrt(yv(0)*yv(0)+yv(1)*yv(1));
-+
-+ p1 = xform.transform((x_min+x_max)/2, (y_min+y_max)/2, z_min, false);
-+ p2 = xform.transform((x_min+x_max)/2, (y_min+y_max)/2, z_max, false);
-+ zv(0) = xround(p2(0)-p1(0));
-+ zv(1) = xround (p2(1)-p1(1));
-+ zv(2) = (p2(2)-p1(2));
-+ if (zv(0) == 0 && zv(1) == 0)
-+ zstate = AXE_DEPTH_DIR;
-+ else if (zv(2) == 0)
-+ {
-+ if (zv(0) == 0)
-+ zstate = AXE_VERT_DIR;
-+ else if (zv(1) == 0)
-+ zstate = AXE_HORZ_DIR;
-+ }
-+ double zPlane;
-+ if (zv(2) == 0)
-+ if (zv(1) == 0)
-+ zPlane = (zv(0) > 0 ? z_min : z_max);
-+ else
-+ zPlane = (zv(1) < 0 ? z_min : z_max);
-+ else
-+ zPlane = (zv(2) < 0 ? z_min : z_max);
-+ double zPlaneN = (zPlane == z_min ? z_max : z_min);
-+ double fz = (z_max-z_min)/sqrt(zv(0)*zv(0)+zv(1)*zv(1));
-+
-+ bool mode2d = (((xstate > AXE_DEPTH_DIR ? 1 : 0) +
-+ (ystate > AXE_DEPTH_DIR ? 1 : 0) +
-+ (zstate > AXE_DEPTH_DIR ? 1 : 0)) == 2);
-+ if (props.tickdirmode_is ("auto"))
-+ {
-+ // FIXME: tickdir should be updated (code below comes
-+ // from JHandles)
-+ //autoMode++;
-+ //TickDir.set(mode2d ? "in" : "out", true);
-+ //autoMode--;
-+ }
-+
-+ // FIXME: use ticklength property
-+ double xticklen = 7, yticklen = 7, zticklen = 7;
-+
-+ //double tickdir = (props.tickdir_is ("in") ? -1 : 1);
-+ double tickdir = (props.tickdirmode_is ("auto") ?
-+ (mode2d ? -1 : 1) :
-+ (props.tickdir_is ("in") ? -1 : 1));
-+ double xtickoffset = (mode2d && tickdir < 0 ? 0 : xticklen) + 5;
-+ double ytickoffset = (mode2d && tickdir < 0 ? 0 : yticklen) + 5;
-+ double ztickoffset = (mode2d && tickdir < 0 ? 0 : zticklen) + 5;
-+
-+ bool xySym = (xd*yd*(xPlane-xPlaneN)*(yPlane-yPlaneN) > 0);
-+ bool x2Dtop = false;
-+ bool y2Dright = false;
-+ double zpTick = zPlane;
-+
-+ /* 2D mode */
-+ if (xstate == AXE_HORZ_DIR && ystate == AXE_VERT_DIR)
-+ {
-+ if (props.xaxislocation_is ("top"))
-+ {
-+ double tmp = yPlane;
-+ yPlane = yPlaneN;
-+ yPlaneN = tmp;
-+ x2Dtop = true;
-+ }
-+ if (props.yaxislocation_is ("right"))
-+ {
-+ double tmp = xPlane;
-+ xPlane = xPlaneN;
-+ xPlaneN = tmp;
-+ y2Dright = true;
-+ }
-+ if (props.layer_is ("top"))
-+ zpTick = zPlaneN;
-+ }
-+
-+ Matrix axe_color = props.get_color_rgb ();
-+ bool visible = props.is_visible ();
-+ bool box = props.is_box ();
-+
-+ // Axes planes
-+
-+ if (axe_color.numel () > 0 && visible)
-+ {
-+ set_color (axe_color);
-+ set_polygon_offset (true, 2.5);
-+
-+ glBegin (GL_QUADS);
-+
-+ // X plane
-+ glVertex3d (xPlane, y_min, z_min);
-+ glVertex3d (xPlane, y_max, z_min);
-+ glVertex3d (xPlane, y_max, z_max);
-+ glVertex3d (xPlane, y_min, z_max);
-+
-+ // Y plane
-+ glVertex3d (x_min, yPlane, z_min);
-+ glVertex3d (x_max, yPlane, z_min);
-+ glVertex3d (x_max, yPlane, z_max);
-+ glVertex3d (x_min, yPlane, z_max);
-+
-+ // Z plane
-+ glVertex3d (x_min, y_min, zPlane);
-+ glVertex3d (x_max, y_min, zPlane);
-+ glVertex3d (x_max, y_max, zPlane);
-+ glVertex3d (x_min, y_max, zPlane);
-+
-+ glEnd ();
-+
-+ set_polygon_offset (false);
-+ }
-+
-+ // Axes box
-+
-+ set_linestyle ("-", true);
-+ set_linewidth (props.get_linewidth ());
-+
-+ if (visible)
-+ {
-+ glBegin (GL_LINES);
-+
-+ // X box
-+ set_color (props.get_xcolor_rgb ());
-+ glVertex3d (xPlaneN, yPlaneN, zPlane);
-+ glVertex3d (xPlane, yPlaneN, zPlane);
-+ if (box)
-+ {
-+ glVertex3d (xPlaneN, yPlane, zPlane);
-+ glVertex3d (xPlane, yPlane, zPlane);
-+ glVertex3d (xPlaneN, yPlane, zPlaneN);
-+ glVertex3d (xPlane, yPlane, zPlaneN);
-+ glVertex3d (xPlaneN, yPlaneN, zPlaneN);
-+ glVertex3d (xPlane, yPlaneN, zPlaneN);
-+ }
-+
-+ // Y box
-+ set_color (props.get_ycolor_rgb ());
-+ glVertex3d (xPlaneN, yPlaneN, zPlane);
-+ glVertex3d (xPlaneN, yPlane, zPlane);
-+ if (box)
-+ {
-+ glVertex3d (xPlane, yPlaneN, zPlane);
-+ glVertex3d (xPlane, yPlane, zPlane);
-+ glVertex3d (xPlane, yPlaneN, zPlaneN);
-+ glVertex3d (xPlane, yPlane, zPlaneN);
-+ glVertex3d (xPlaneN, yPlaneN, zPlaneN);
-+ glVertex3d (xPlaneN, yPlane, zPlaneN);
-+ }
-+
-+ // Z box
-+ set_color (props.get_zcolor_rgb ());
-+ if (xySym)
-+ {
-+ glVertex3d (xPlaneN, yPlane, zPlaneN);
-+ glVertex3d (xPlaneN, yPlane, zPlane);
-+ }
-+ else
-+ {
-+ glVertex3d (xPlane, yPlaneN, zPlaneN);
-+ glVertex3d (xPlane, yPlaneN, zPlane);
-+ }
-+ if (box)
-+ {
-+ glVertex3d (xPlane, yPlane, zPlaneN);
-+ glVertex3d (xPlane, yPlane, zPlane);
-+ if (xySym)
-+ {
-+ glVertex3d (xPlane, yPlaneN, zPlaneN);
-+ glVertex3d (xPlane, yPlaneN, zPlane);
-+ }
-+ else
-+ {
-+ glVertex3d (xPlaneN, yPlane, zPlaneN);
-+ glVertex3d (xPlaneN, yPlane, zPlane);
-+ }
-+ glVertex3d (xPlaneN, yPlaneN, zPlaneN);
-+ glVertex3d (xPlaneN, yPlaneN, zPlane);
-+ }
-+
-+ glEnd ();
-+ }
-+
-+ std::string gridstyle = props.get_gridlinestyle ();
-+ std::string minorgridstyle = props.get_minorgridlinestyle ();
-+
-+ // X grid
-+
-+ if (visible && xstate != AXE_DEPTH_DIR)
-+ {
-+ bool do_xgrid = (props.is_xgrid () && (gridstyle != "none"));
-+ bool do_xminorgrid = (props.is_xminorgrid () && (minorgridstyle != "none"));
-+ bool do_xminortick = props.is_xminortick ();
-+ Matrix xticks = xform.xscale (props.get_xtick ().matrix_value ());
-+ // FIXME: use pre-computed minor ticks
-+ Matrix xmticks;
-+ // FIXME: use xticklabels property
-+ string_vector xticklabels;
-+ int wmax = 0, hmax = 0;
-+ bool tick_along_z = xisinf (fy);
-+ Matrix tickpos (xticks.numel (), 3);
-+
-+ set_color (props.get_xcolor_rgb ());
-+
-+ // grid lines
-+ if (do_xgrid)
-+ {
-+ set_linestyle (gridstyle, true);
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < xticks.numel (); i++)
-+ {
-+ double xval = xticks(i);
-+
-+ glVertex3d (xval, yPlaneN, zpTick);
-+ glVertex3d (xval, yPlane, zpTick);
-+ if (zstate != AXE_DEPTH_DIR)
-+ {
-+ glVertex3d (xval, yPlane, zPlaneN);
-+ glVertex3d (xval, yPlane, zPlane);
-+ }
-+ }
-+ glEnd ();
-+ set_linestyle ("-", true);
-+ }
-+
-+ // tick marks
-+ if (tick_along_z)
-+ {
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < xticks.numel (); i++)
-+ {
-+ double xval = xticks(i);
-+
-+ glVertex3d (xval, yPlaneN, zPlane);
-+ glVertex3d (xval, yPlaneN, zPlane+signum(zPlane-zPlaneN)*fz*xticklen*tickdir);
-+ if (box && xstate != AXE_ANY_DIR)
-+ {
-+ glVertex3d (xval, yPlaneN, zPlaneN);
-+ glVertex3d (xval, yPlaneN,
-+ zPlaneN+signum(zPlaneN-zPlane)*fz*xticklen*tickdir);
-+ }
-+ tickpos(i,0) = xval;
-+ tickpos(i,1) = yPlaneN;
-+ tickpos(i,2) = zPlane+signum(zPlane-zPlaneN)*fz*xtickoffset;
-+ }
-+ glEnd ();
-+ }
-+ else
-+ {
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < xticks.numel (); i++)
-+ {
-+ double xval = xticks(i);
-+
-+ glVertex3d (xval, yPlaneN, zpTick);
-+ glVertex3d (xval, yPlaneN+signum(yPlaneN-yPlane)*fy*xticklen*tickdir, zpTick);
-+ if (box && xstate != AXE_ANY_DIR)
-+ {
-+ glVertex3d (xval, yPlane, zpTick);
-+ glVertex3d (xval,
-+ yPlane+signum(yPlane-yPlaneN)*fy*xticklen*tickdir, zpTick);
-+ }
-+ tickpos(i,0) = xval;
-+ tickpos(i,1) = yPlaneN+signum(yPlaneN-yPlane)*fy*xtickoffset;
-+ tickpos(i,2) = zPlane;
-+ }
-+ glEnd ();
-+ }
-+
-+ // FIXME: tick texts
-+
-+ // minor grid lines
-+ if (do_xminorgrid)
-+ {
-+ set_linestyle (minorgridstyle, true);
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < xmticks.numel (); i++)
-+ {
-+ double xval = xmticks(i);
-+
-+ glVertex3d (xval, yPlaneN, zpTick);
-+ glVertex3d (xval, yPlane, zpTick);
-+ if (zstate != AXE_DEPTH_DIR)
-+ {
-+ glVertex3d (xval, yPlane, zPlaneN);
-+ glVertex3d (xval, yPlane, zPlane);
-+ }
-+ }
-+ glEnd ();
-+ set_linestyle ("-", true);
-+ }
-+
-+ // minor tick marks
-+ if (do_xminortick)
-+ {
-+ if (tick_along_z)
-+ {
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < xmticks.numel (); i++)
-+ {
-+ double xval = xmticks(i);
-+
-+ glVertex3d (xval, yPlaneN, zPlane);
-+ glVertex3d (xval, yPlaneN,
-+ zPlane+signum(zPlane-zPlaneN)*fz*xticklen/2*tickdir);
-+ if (box && xstate != AXE_ANY_DIR)
-+ {
-+ glVertex3d (xval, yPlaneN, zPlaneN);
-+ glVertex3d (xval, yPlaneN,
-+ zPlaneN+signum(zPlaneN-zPlane)*fz*xticklen/2*tickdir);
-+ }
-+ }
-+ glEnd ();
-+ }
-+ else
-+ {
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < xmticks.numel (); i++)
-+ {
-+ double xval = xmticks(i);
-+
-+ glVertex3d (xval, yPlaneN, zpTick);
-+ glVertex3d (xval,
-+ yPlaneN+signum(yPlaneN-yPlane)*fy*xticklen/2*tickdir, zpTick);
-+ if (box && xstate != AXE_ANY_DIR)
-+ {
-+ glVertex3d (xval, yPlane, zpTick);
-+ glVertex3d (xval,
-+ yPlane+signum(yPlane-yPlaneN)*fy*xticklen/2*tickdir, zpTick);
-+ }
-+ }
-+ glEnd ();
-+ }
-+ }
-+
-+ text::properties& xlabel_props =
-+ reinterpret_cast<text::properties&> (gh_manager::get_object (props.get_xlabel ()).get_properties ());
-+
-+ // FIXME: auto-positioning should be disabled if the
-+ // label has been positioned manually
-+ if (! xlabel_props.get_string ().empty ())
-+ {
-+ xlabel_props.set_horizontalalignment (xstate > AXE_DEPTH_DIR ? "center" : (xySym ? "left" : "right"));
-+ xlabel_props.set_verticalalignment (xstate == AXE_VERT_DIR ? "bottom" : (zd*zv(2) <= 0 ? "top" : "bottom"));
-+
-+ double angle = 0;
-+ ColumnVector p = graphics_xform::xform_vector ((x_min+x_max)/2, yPlaneN, zPlane);
-+
-+ if (tick_along_z)
-+ p(2) += (signum(zPlane-zPlaneN)*fz*xtickoffset);
-+ else
-+ p(1) += (signum(yPlaneN-yPlane)*fy*xtickoffset);
-+ p = xform.transform (p(0), p(1), p(2), false);
-+ switch (xstate)
-+ {
-+ case AXE_ANY_DIR:
-+ p(0) += (xySym ? wmax : -wmax);
-+ p(1) += (zd*zv(2) <= 0 ? hmax : -hmax);
-+ break;
-+ case AXE_VERT_DIR:
-+ p(0) -= wmax;
-+ angle = 90;
-+ break;
-+ case AXE_HORZ_DIR:
-+ p(1) += hmax;
-+ break;
-+ }
-+ p = xform.untransform (p(0), p(1), p(2), true);
-+ xlabel_props.set_position (p.extract_n (0, 3).transpose ());
-+ xlabel_props.set_rotation (angle);
-+ }
-+ }
-+
-+ // Y grid
-+
-+ if (ystate != AXE_DEPTH_DIR && visible)
-+ {
-+ bool do_ygrid = (props.is_ygrid () && (gridstyle != "none"));
-+ bool do_yminorgrid = (props.is_yminorgrid () && (minorgridstyle != "none"));
-+ bool do_yminortick = props.is_yminortick ();
-+ Matrix yticks = xform.yscale (props.get_ytick ().matrix_value ());
-+ // FIXME: use pre-computed minor ticks
-+ Matrix ymticks;
-+ // FIXME: use yticklabels property
-+ string_vector yticklabels;
-+ int wmax = 0, hmax = 0;
-+ bool tick_along_z = xisinf (fx);
-+ Matrix tickpos (yticks.numel (), 3);
-+
-+ set_color (props.get_ycolor_rgb ());
-+
-+ // grid lines
-+ if (do_ygrid)
-+ {
-+ set_linestyle (gridstyle, true);
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < yticks.numel (); i++)
-+ {
-+ double yval = yticks(i);
-+
-+ glVertex3d (xPlaneN, yval, zpTick);
-+ glVertex3d (xPlane, yval, zpTick);
-+ if (zstate != AXE_DEPTH_DIR)
-+ {
-+ glVertex3d (xPlane, yval, zPlaneN);
-+ glVertex3d (xPlane, yval, zPlane);
-+ }
-+ }
-+ glEnd ();
-+ set_linestyle ("-", true);
-+ }
-+
-+ // tick marks
-+ if (tick_along_z)
-+ {
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < yticks.numel (); i++)
-+ {
-+ double yval = yticks(i);
-+
-+ glVertex3d (xPlaneN, yval, zPlane);
-+ glVertex3d (xPlaneN, yval, zPlane+signum(zPlane-zPlaneN)*fz*yticklen*tickdir);
-+ if (box && ystate != AXE_ANY_DIR)
-+ {
-+ glVertex3d (xPlaneN, yval, zPlaneN);
-+ glVertex3d (xPlaneN, yval,
-+ zPlaneN+signum(zPlaneN-zPlane)*fz*yticklen*tickdir);
-+ }
-+ tickpos(i,0) = xPlaneN;
-+ tickpos(i,1) = yval;
-+ tickpos(i,2) = zPlane+signum(zPlane-zPlaneN)*fz*ytickoffset;
-+ }
-+ glEnd ();
-+ }
-+ else
-+ {
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < yticks.numel (); i++)
-+ {
-+ double yval = yticks(i);
-+
-+ glVertex3d (xPlaneN, yval, zpTick);
-+ glVertex3d (xPlaneN+signum(xPlaneN-xPlane)*fx*yticklen*tickdir, yval, zpTick);
-+ if (box && ystate != AXE_ANY_DIR)
-+ {
-+ glVertex3d (xPlane, yval, zpTick);
-+ glVertex3d (xPlane+signum(xPlane-xPlaneN)*fx*yticklen*tickdir,
-+ yval, zpTick);
-+ }
-+ tickpos(i,0) = xPlaneN+signum(xPlaneN-xPlane)*fx*ytickoffset;
-+ tickpos(i,1) = yval;
-+ tickpos(i,2) = zPlane;
-+ }
-+ glEnd ();
-+ }
-+
-+ // FIXME: tick texts
-+
-+ // minor grid lines
-+ if (do_yminorgrid)
-+ {
-+ set_linestyle (minorgridstyle, true);
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < ymticks.numel (); i++)
-+ {
-+ double yval = ymticks(i);
-+
-+ glVertex3d (xPlaneN, yval, zpTick);
-+ glVertex3d (xPlane, yval, zpTick);
-+ if (zstate != AXE_DEPTH_DIR)
-+ {
-+ glVertex3d (xPlane, yval, zPlaneN);
-+ glVertex3d (xPlane, yval, zPlane);
-+ }
-+ }
-+ glEnd ();
-+ set_linestyle ("-", true);
-+ }
-+
-+ // minor tick marks
-+ if (do_yminortick)
-+ {
-+ if (tick_along_z)
-+ {
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < ymticks.numel (); i++)
-+ {
-+ double yval = ymticks(i);
-+
-+ glVertex3d (xPlaneN, yval, zPlane);
-+ glVertex3d (xPlaneN, yval,
-+ zPlane+signum(zPlane-zPlaneN)*fz*yticklen/2*tickdir);
-+ if (box && ystate != AXE_ANY_DIR)
-+ {
-+ glVertex3d (xPlaneN, yval, zPlaneN);
-+ glVertex3d (xPlaneN, yval,
-+ zPlaneN+signum(zPlaneN-zPlane)*fz*yticklen/2*tickdir);
-+ }
-+ }
-+ glEnd ();
-+ }
-+ else
-+ {
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < ymticks.numel (); i++)
-+ {
-+ double yval = ymticks(i);
-+
-+ glVertex3d (xPlaneN, yval, zpTick);
-+ glVertex3d (xPlaneN+signum(xPlaneN-xPlane)*fx*yticklen/2*tickdir,
-+ yval, zpTick);
-+ if (box && ystate != AXE_ANY_DIR)
-+ {
-+ glVertex3d (xPlane, yval, zpTick);
-+ glVertex3d (xPlane+signum(xPlane-xPlaneN)*fx*yticklen/2*tickdir,
-+ yval, zpTick);
-+ }
-+ }
-+ glEnd ();
-+ }
-+ }
-+
-+ text::properties& ylabel_props =
-+ reinterpret_cast<text::properties&> (gh_manager::get_object (props.get_ylabel ()).get_properties ());
-+
-+ // FIXME: auto-positioning should be disabled if the
-+ // label has been positioned manually
-+ if (! ylabel_props.get_string ().empty ())
-+ {
-+ ylabel_props.set_horizontalalignment (ystate > AXE_DEPTH_DIR ? "center" : (!xySym ? "left" : "right"));
-+ ylabel_props.set_verticalalignment (ystate == AXE_VERT_DIR ? "bottom" : (zd*zv(2) <= 0 ? "top" : "bottom"));
-+
-+ double angle = 0;
-+ ColumnVector p = graphics_xform::xform_vector (xPlaneN, (y_min+y_max)/2, zPlane);
-+
-+ if (tick_along_z)
-+ p(2) += (signum(zPlane-zPlaneN)*fz*ytickoffset);
-+ else
-+ p(0) += (signum(xPlaneN-xPlane)*fx*ytickoffset);
-+ p = xform.transform (p(0), p(1), p(2), false);
-+ switch (ystate)
-+ {
-+ case AXE_ANY_DIR:
-+ p(0) += (!xySym ? wmax : -wmax);
-+ p(1) += (zd*zv(2) <= 0 ? hmax : -hmax);
-+ break;
-+ case AXE_VERT_DIR:
-+ p(0) -= wmax;
-+ angle = 90;
-+ break;
-+ case AXE_HORZ_DIR:
-+ p(1) += hmax;
-+ break;
-+ }
-+ p = xform.untransform(p(0), p(1), p(2), true);
-+ ylabel_props.set_position (p.extract_n (0, 3).transpose ());
-+ ylabel_props.set_rotation (angle);
-+ }
-+ }
-+
-+ // Z Grid
-+
-+ if (zstate != AXE_DEPTH_DIR && visible)
-+ {
-+ bool do_zgrid = (props.is_zgrid () && (gridstyle != "none"));
-+ bool do_zminorgrid = (props.is_zminorgrid () && (minorgridstyle != "none"));
-+ bool do_zminortick = props.is_zminortick ();
-+ Matrix zticks = xform.zscale (props.get_ztick ().matrix_value ());
-+ // FIXME: use pre-computed minor ticks
-+ Matrix zmticks;
-+ // FIXME: use zticklabels property
-+ string_vector zticklabels;
-+ int wmax = 0, hmax = 0;
-+ Matrix tickpos (zticks.numel (), 3);
-+
-+ set_color (props.get_zcolor_rgb ());
-+
-+ // grid lines
-+ if (do_zgrid)
-+ {
-+ set_linestyle (gridstyle, true);
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < zticks.numel (); i++)
-+ {
-+ double zval = zticks(i);
-+
-+ glVertex3d (xPlaneN, yPlane, zval);
-+ glVertex3d (xPlane, yPlane, zval);
-+ glVertex3d (xPlane, yPlaneN, zval);
-+ glVertex3d (xPlane, yPlane, zval);
-+ }
-+ glEnd ();
-+ set_linestyle ("-", true);
-+ }
-+
-+ // tick marks
-+ if (xySym)
-+ {
-+ if (xisinf (fy))
-+ {
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < zticks.numel (); i++)
-+ {
-+ double zval = zticks(i);
-+
-+ glVertex3d (xPlaneN, yPlane, zval);
-+ glVertex3d (xPlaneN+signum(xPlaneN-xPlane)*fx*zticklen*tickdir,
-+ yPlane, zval);
-+ if (box && zstate != AXE_ANY_DIR)
-+ {
-+ glVertex3d (xPlane, yPlane, zval);
-+ glVertex3d (xPlane+signum(xPlane-xPlaneN)*fx*zticklen*tickdir,
-+ yPlane, zval);
-+ }
-+ tickpos(i,0) = xPlaneN+signum(xPlaneN-xPlane)*fx*ztickoffset;
-+ tickpos(i,1) = yPlane;
-+ tickpos(i,2) = zval;
-+ }
-+ glEnd ();
-+ }
-+ else
-+ {
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < zticks.numel (); i++)
-+ {
-+ double zval = zticks(i);
-+
-+ glVertex3d (xPlaneN, yPlane, zval);
-+ glVertex3d (xPlaneN, yPlane+signum(yPlane-yPlaneN)*fy*zticklen*tickdir, zval);
-+ tickpos(i,0) = xPlaneN;
-+ tickpos(i,1) = yPlane+signum(yPlane-yPlaneN)*fy*ztickoffset;
-+ tickpos(i,2) = zval;
-+ }
-+ glEnd ();
-+ }
-+ }
-+ else
-+ {
-+ if (xisinf (fx))
-+ {
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < zticks.numel (); i++)
-+ {
-+ double zval = zticks(i);
-+
-+ glVertex3d (xPlane, yPlaneN, zval);
-+ glVertex3d (xPlane, yPlaneN+signum(yPlaneN-yPlane)*fy*zticklen*tickdir, zval);
-+ if (box && zstate != AXE_ANY_DIR)
-+ {
-+ glVertex3d (xPlane, yPlane, zval);
-+ glVertex3d (xPlane, yPlane+signum(yPlane-yPlaneN)*fy*zticklen*tickdir, zval);
-+ }
-+ tickpos(i,0) = xPlane;
-+ tickpos(i,1) = yPlaneN+signum(yPlaneN-yPlane)*fy*ztickoffset;
-+ tickpos(i,2) = zval;
-+ }
-+ glEnd ();
-+ }
-+ else
-+ {
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < zticks.numel (); i++)
-+ {
-+ double zval = zticks(i);
-+
-+ glVertex3d (xPlane, yPlaneN, zval);
-+ glVertex3d (xPlane+signum(xPlane-xPlaneN)*fx*zticklen*tickdir, yPlaneN, zval);
-+ tickpos(i,0) = xPlane+signum(xPlane-xPlaneN)*fx*ztickoffset;
-+ tickpos(i,1) = yPlaneN;
-+ tickpos(i,2) = zval;
-+ }
-+ glEnd ();
-+ }
-+ }
-+
-+ // FIXME: tick texts
-+
-+ // minor grid lines
-+ if (do_zminorgrid)
-+ {
-+ set_linestyle (minorgridstyle, true);
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < zmticks.numel (); i++)
-+ {
-+ double zval = zmticks(i);
-+
-+ glVertex3d (xPlaneN, yPlane, zval);
-+ glVertex3d (xPlane, yPlane, zval);
-+ glVertex3d (xPlane, yPlaneN, zval);
-+ glVertex3d (xPlane, yPlane, zval);
-+ }
-+ glEnd ();
-+ set_linestyle ("-", true);
-+ }
-+
-+ // minor tick marks
-+ if (do_zminortick)
-+ {
-+ if (xySym)
-+ {
-+ if (xisinf (fy))
-+ {
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < zmticks.numel (); i++)
-+ {
-+ double zval = zmticks(i);
-+
-+ glVertex3d (xPlaneN, yPlane, zval);
-+ glVertex3d (xPlaneN+signum(xPlaneN-xPlane)*fx*zticklen/2*tickdir,
-+ yPlane, zval);
-+ if (box && zstate != AXE_ANY_DIR)
-+ {
-+ glVertex3d (xPlane, yPlane, zval);
-+ glVertex3d (xPlane+signum(xPlane-xPlaneN)*fx*zticklen/2*tickdir,
-+ yPlane, zval);
-+ }
-+ }
-+ glEnd ();
-+ }
-+ else
-+ {
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < zmticks.numel (); i++)
-+ {
-+ double zval = zmticks(i);
-+
-+ glVertex3d (xPlaneN, yPlane, zval);
-+ glVertex3d (xPlaneN, yPlane+signum(yPlane-yPlaneN)*fy*zticklen/2*tickdir, zval);
-+ }
-+ glEnd ();
-+ }
-+ }
-+ else
-+ {
-+ if (xisinf (fx))
-+ {
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < zmticks.numel (); i++)
-+ {
-+ double zval = zmticks(i);
-+
-+ glVertex3d (xPlane, yPlaneN, zval);
-+ glVertex3d (xPlane, yPlaneN+signum(yPlaneN-yPlane)*fy*zticklen/2*tickdir, zval);
-+ if (box && zstate != AXE_ANY_DIR)
-+ {
-+ glVertex3d (xPlane, yPlane, zval);
-+ glVertex3d (xPlane, yPlane+signum(yPlane-yPlaneN)*fy*zticklen/2*tickdir, zval);
-+ }
-+ }
-+ glEnd ();
-+ }
-+ else
-+ {
-+ glBegin (GL_LINES);
-+ for (int i = 0; i < zmticks.numel (); i++)
-+ {
-+ double zval = zmticks(i);
-+
-+ glVertex3d (xPlane, yPlaneN, zval);
-+ glVertex3d (xPlane+signum(xPlane-xPlaneN)*fx*zticklen/2*tickdir, yPlaneN, zval);
-+ }
-+ glEnd ();
-+ }
-+ }
-+ }
-+
-+ text::properties& zlabel_props =
-+ reinterpret_cast<text::properties&> (gh_manager::get_object (props.get_zlabel ()).get_properties ());
-+
-+ // FIXME: auto-positioning should be disabled if the
-+ // label has been positioned manually
-+ if (! zlabel_props.get_string ().empty ())
-+ {
-+ bool camAuto = props.cameraupvectormode_is ("auto");
-+
-+ zlabel_props.set_horizontalalignment ((zstate > AXE_DEPTH_DIR || camAuto) ? "center" : "right");
-+ zlabel_props.set_verticalalignment(zstate == AXE_VERT_DIR ? "bottom" : ((zd*zv(2) < 0 || camAuto) ? "bottom" : "top"));
-+
-+ double angle = 0;
-+ ColumnVector p;
-+
-+ if (xySym)
-+ {
-+ p = graphics_xform::xform_vector (xPlaneN, yPlane, (z_min+z_max)/2);
-+ if (xisinf (fy))
-+ p(0) += (signum(xPlaneN-xPlane)*fx*ztickoffset);
-+ else
-+ p(1) += (signum(yPlane-yPlaneN)*fy*ztickoffset);
-+ }
-+ else
-+ {
-+ p = graphics_xform::xform_vector (xPlane, yPlaneN, (z_min+z_max)/2);
-+ if (xisinf (fx))
-+ p(1) += (signum(yPlaneN-yPlane)*fy*ztickoffset);
-+ else
-+ p(0) += (signum(xPlane-xPlaneN)*fx*ztickoffset);
-+ }
-+ p = xform.transform (p(0), p(1), p(2), false);
-+ switch (zstate)
-+ {
-+ case AXE_ANY_DIR:
-+ if (camAuto)
-+ {
-+ p(0) -= wmax;
-+ angle = 90;
-+ }
-+ /* FIXME: what's the correct offset?
-+ p[0] += (!xySym ? wmax : -wmax);
-+ p[1] += (zd*zv[2] <= 0 ? hmax : -hmax);
-+ */
-+ break;
-+ case AXE_VERT_DIR:
-+ p(0) -= wmax;
-+ angle = 90;
-+ break;
-+ case AXE_HORZ_DIR:
-+ p(1) += hmax;
-+ break;
-+ }
-+ p = xform.untransform (p(0), p(1), p(2), true);
-+ zlabel_props.set_position (p.extract_n (0, 3).transpose ());
-+ zlabel_props.set_rotation (angle);
-+ }
-+ }
-+
-+ set_linestyle ("-");
-+
-+ // Title
-+
-+ text::properties& title_props =
-+ reinterpret_cast<text::properties&> (gh_manager::get_object (props.get_title ()).get_properties ());
-+
-+ // FIXME: auto-positioning should be disabled if the
-+ // title has been positioned manually
-+ if (! title_props.get_string ().empty ())
-+ {
-+ Matrix bb = props.get_boundingbox (true);
-+ ColumnVector p = xform.untransform (bb(0)+bb(2)/2, (bb(1)-10),
-+ (x_zlim(0)+x_zlim(1))/2, true);
-+ title_props.set_position (p.extract_n(0, 3).transpose ());
-+ }
-+
-+ set_clipbox (x_min, x_max, y_min, y_max, z_min, z_max);
-+
-+ // Children
-+
-+ if (antialias == GL_TRUE)
-+ glEnable (GL_LINE_SMOOTH);
-+
-+ Matrix children = props.get_children ();
-+ std::list<graphics_object> obj_list;
-+ std::list<graphics_object>::iterator it;
-+
-+ // 1st pass: draw light objects
-+
-+ for (int i = 0; i < children.numel (); i++)
-+ {
-+ graphics_object go = gh_manager::get_object (children (i));
-+
-+ if (go.get_properties ().is_visible ())
-+ {
-+ if (go.isa ("light"))
-+ draw (go);
-+ else
-+ obj_list.push_back (go);
-+ }
-+ }
-+
-+ // 2nd pass: draw other objects (with units set to "data")
-+
-+ it = obj_list.begin ();
-+ while (it != obj_list.end ())
-+ {
-+ graphics_object go = (*it);
-+
-+ // FIXME: check whether object has "units" property and it is set to "data"
-+ if (! go.isa ("text") || go.get ("units").string_value () == "data")
-+ {
-+ set_clipping (go.get_properties ().is_clipping ());
-+ draw (go);
-+
-+ it = obj_list.erase (it);
-+ }
-+ else
-+ it++;
-+ }
-+
-+ // 3rd pass: draw remaining objects
-+
-+ for (it = obj_list.begin (); it != obj_list.end (); it++)
-+ {
-+ graphics_object go = (*it);
-+
-+ set_clipping (go.get_properties ().is_clipping ());
-+ draw (go);
-+ }
-+
-+ set_clipping (false);
-+ // FIXME: finalize rendering (transparency processing)
-+ // FIXME: draw zoom box, if needed
-+}
-+
-+void
-+opengl_renderer::draw (const line::properties& props)
-+{
-+ Matrix x = xform.xscale (props.get_xdata ().matrix_value ());
-+ Matrix y = xform.yscale (props.get_ydata ().matrix_value ());
-+ Matrix z = xform.zscale (props.get_zdata ().matrix_value ());
-+
-+ bool has_z = (z.numel () > 0);
-+ int n = static_cast<int> (::xmin (::xmin (x.numel (), y.numel ()), (has_z ? z.numel () : INT_MAX)));
-+ octave_uint8 clip_mask = (props.is_clipping () ? 0x7F : 0x40), clip_ok (0x40);
-+
-+ std::vector<octave_uint8> clip (n);
-+
-+ if (has_z)
-+ for (int i = 0; i < n; i++)
-+ clip[i] = (clip_code (x(i), y(i), z(i)) & clip_mask);
-+ else
-+ {
-+ double z_mid = (zmin+zmax)/2;
-+
-+ for (int i = 0; i < n; i++)
-+ clip[i] = (clip_code (x(i), y(i), z_mid) & clip_mask);
-+ }
-+
-+ if (! props.linestyle_is ("none"))
-+ {
-+ set_color (props.get_color_rgb ());
-+ set_linestyle (props.get_linestyle (), false);
-+ set_linewidth (props.get_linewidth ());
-+
-+ if (has_z)
-+ {
-+ bool flag = false;
-+
-+ for (int i = 1; i < n; i++)
-+ {
-+ if ((clip[i-1] & clip[i]) == clip_ok)
-+ {
-+ if (! flag)
-+ {
-+ flag = true;
-+ glBegin (GL_LINE_STRIP);
-+ glVertex3d (x(i-1), y(i-1), z(i-1));
-+ }
-+ glVertex3d (x(i), y(i), z(i));
-+ }
-+ else if (flag)
-+ {
-+ flag = false;
-+ glEnd ();
-+ }
-+ }
-+
-+ if (flag)
-+ glEnd ();
-+ }
-+ else
-+ {
-+ bool flag = false;
-+
-+ for (int i = 1; i < n; i++)
-+ {
-+ if ((clip[i-1] & clip[i]) == clip_ok)
-+ {
-+ if (! flag)
-+ {
-+ flag = true;
-+ glBegin (GL_LINE_STRIP);
-+ glVertex2d (x(i-1), y(i-1));
-+ }
-+ glVertex2d (x(i), y(i));
-+ }
-+ else if (flag)
-+ {
-+ flag = false;
-+ glEnd ();
-+ }
-+ }
-+
-+ if (flag)
-+ glEnd ();
-+ }
-+
-+ set_linewidth (0.5);
-+ set_linestyle ("-");
-+ }
-+
-+ set_clipping (false);
-+
-+ if (! props.marker_is ("none") &&
-+ ! (props.markeredgecolor_is ("none")
-+ && props.markerfacecolor_is ("none")))
-+ {
-+ Matrix lc, fc;
-+
-+ if (props.markeredgecolor_is ("auto"))
-+ lc = props.get_color_rgb ();
-+ else if (! props.markeredgecolor_is ("none"))
-+ lc = props.get_markeredgecolor_rgb ();
-+
-+ if (props.markerfacecolor_is ("auto"))
-+ fc = props.get_color_rgb ();
-+ else if (! props.markerfacecolor_is ("none"))
-+ fc = props.get_markerfacecolor_rgb ();
-+
-+ init_marker (props.get_marker (), props.get_markersize (),
-+ props.get_linewidth ());
-+
-+ for (int i = 0; i < n; i++)
-+ {
-+ if (clip[i] == clip_ok)
-+ draw_marker (x(i), y(i), (has_z ? z(i) : 0), lc, fc);
-+ }
-+
-+ end_marker ();
-+ }
-+
-+ set_clipping (props.is_clipping ());
-+}
-+
-+void
-+opengl_renderer::draw (const surface::properties& props)
-+{
-+ Matrix x = xform.xscale (props.get_xdata ().matrix_value ());
-+ Matrix y = xform.yscale (props.get_ydata ().matrix_value ());
-+ Matrix z = xform.zscale (props.get_zdata ().matrix_value ());
-+
-+ int zr = z.rows (), zc = z.columns ();
-+
-+ NDArray c;
-+ NDArray n = props.get_vertexnormals ().array_value ();
-+
-+ // FIXME: handle transparency
-+ Matrix a;
-+
-+ if (props.facelighting_is ("phong") || props.edgelighting_is ("phong"))
-+ warning ("opengl_renderer::draw: phong light model not supported");
-+
-+ int fc_mode = (props.facecolor_is_rgb () ? 0 :
-+ (props.facecolor_is ("flat") ? 1 :
-+ (props.facecolor_is ("interp") ? 2 :
-+ (props.facecolor_is ("texturemap") ? 3 : -1))));
-+ int fl_mode = (props.facelighting_is ("none") ? 0 :
-+ (props.facelighting_is ("flat") ? 1 : 2));
-+ int fa_mode = (props.facealpha_is_double () ? 0 :
-+ (props.facealpha_is ("flat") ? 1 : 2));
-+ int ec_mode = (props.edgecolor_is_rgb () ? 0 :
-+ (props.edgecolor_is ("flat") ? 1 :
-+ (props.edgecolor_is ("interp") ? 2 : -1)));
-+ int el_mode = (props.edgelighting_is ("none") ? 0 :
-+ (props.edgelighting_is ("flat") ? 1 : 2));
-+ int ea_mode = (props.edgealpha_is_double () ? 0 :
-+ (props.edgealpha_is ("flat") ? 1 : 2));
-+
-+ Matrix fcolor = (fc_mode == 3 ? Matrix (1, 3, 1.0) : props.get_facecolor_rgb ());
-+ Matrix ecolor = props.get_edgecolor_rgb ();
-+
-+ float as = props.get_ambientstrength ();
-+ float ds = props.get_diffusestrength ();
-+ float ss = props.get_specularstrength ();
-+ float se = props.get_specularexponent ();
-+ float cb[4] = { 0, 0, 0, 1 };
-+
-+ opengl_texture tex;
-+
-+ int i1, i2, j1, j2;
-+ bool x_mat = (x.rows () == z.rows ());
-+ bool y_mat = (y.columns () == z.columns ());
-+
-+ i1 = i2 = j1 = j2 = 0;
-+
-+ boolMatrix clip (z.dims (), false);
-+
-+ for (int i = 0; i < zr; i++)
-+ {
-+ if (x_mat)
-+ i1 = i;
-+
-+ for (int j = 0; j < zc; j++)
-+ {
-+ if (y_mat)
-+ j1 = j;
-+
-+ clip(i,j) = is_nan_or_inf (x(i1,j), y(i,j1), z(i,j));
-+ }
-+ }
-+
-+ if ((fc_mode > 0 && fc_mode < 3) || ec_mode > 0)
-+ c = props.get_color_data ().array_value ();
-+
-+ if (fa_mode > 0 || ea_mode > 0)
-+ {
-+ // FIXME: implement alphadata conversion
-+ //a = props.get_alpha_data ();
-+ }
-+
-+ if (fl_mode > 0 || el_mode > 0)
-+ {
-+ float buf[4] = { ss, ss, ss, 1 };
-+
-+ glMaterialfv (LIGHT_MODE, GL_SPECULAR, buf);
-+ glMaterialf (LIGHT_MODE, GL_SHININESS, se);
-+ }
-+
-+ // FIXME: good candidate for caching, transfering pixel
-+ // data to OpenGL is time consuming.
-+ if (fc_mode == 3)
-+ tex = opengl_texture::create (props.get_color_data ());
-+
-+ if (! props.facecolor_is ("none"))
-+ {
-+ if (props.get_facealpha_double () == 1)
-+ {
-+ if (fc_mode == 0 || fc_mode == 3)
-+ {
-+ glColor3dv (fcolor.data ());
-+ if (fl_mode > 0)
-+ {
-+ for (int i = 0; i < 3; i++)
-+ cb[i] = (as * fcolor(i));
-+ glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-+
-+ for (int i = 0; i < 3; i++)
-+ cb[i] *= (ds / as);
-+ glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-+ }
-+ }
-+
-+ if (fl_mode > 0)
-+ glEnable (GL_LIGHTING);
-+ glShadeModel ((fc_mode == 2 || fl_mode == 2) ? GL_SMOOTH : GL_FLAT);
-+ set_polygon_offset (true, 1);
-+ if (fc_mode == 3)
-+ glEnable (GL_TEXTURE_2D);
-+
-+ for (int i = 1; i < zc; i++)
-+ {
-+ if (y_mat)
-+ {
-+ i1 = i-1;
-+ i2 = i;
-+ }
-+
-+ for (int j = 1; j < zr; j++)
-+ {
-+ if (clip(j-1, i-1) || clip (j, i-1)
-+ || clip (j-1, i) || clip (j, i))
-+ continue;
-+
-+ if (x_mat)
-+ {
-+ j1 = j-1;
-+ j2 = j;
-+ }
-+
-+ glBegin (GL_QUADS);
-+
-+ // Vertex 1
-+ if (fc_mode == 3)
-+ tex.tex_coord (double (i-1) / (zc-1), double (j-1) / (zr-1));
-+ else if (fc_mode > 0)
-+ {
-+ // FIXME: is there a smarter way to do this?
-+ for (int k = 0; k < 3; k++)
-+ cb[k] = c(j-1, i-1, k);
-+ glColor3fv (cb);
-+
-+ if (fl_mode > 0)
-+ {
-+ for (int k = 0; k < 3; k++)
-+ cb[k] *= as;
-+ glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-+
-+ for (int k = 0; k < 3; k++)
-+ cb[k] *= (ds / as);
-+ glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-+ }
-+ }
-+ if (fl_mode > 0)
-+ glNormal3d (n(j-1,i-1,0), n(j-1,i-1,1), n(j-1,i-1,2));
-+ glVertex3d (x(j1,i-1), y(j-1,i1), z(j-1,i-1));
-+
-+ // Vertex 2
-+ if (fc_mode == 3)
-+ tex.tex_coord (double (i) / (zc-1), double (j-1) / (zr-1));
-+ else if (fc_mode == 2)
-+ {
-+ for (int k = 0; k < 3; k++)
-+ cb[k] = c(j-1, i, k);
-+ glColor3fv (cb);
-+
-+ if (fl_mode > 0)
-+ {
-+ for (int k = 0; k < 3; k++)
-+ cb[k] *= as;
-+ glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-+
-+ for (int k = 0; k < 3; k++)
-+ cb[k] *= (ds / as);
-+ glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-+ }
-+ }
-+ if (fl_mode == 2)
-+ glNormal3d (n(j-1,i,0), n(j-1,i,1), n(j-1,i,2));
-+ glVertex3d (x(j1,i), y(j-1,i2), z(j-1,i));
-+
-+ // Vertex 3
-+ if (fc_mode == 3)
-+ tex.tex_coord (double (i) / (zc-1), double (j) / (zr-1));
-+ else if (fc_mode == 2)
-+ {
-+ for (int k = 0; k < 3; k++)
-+ cb[k] = c(j, i, k);
-+ glColor3fv (cb);
-+
-+ if (fl_mode > 0)
-+ {
-+ for (int k = 0; k < 3; k++)
-+ cb[k] *= as;
-+ glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-+
-+ for (int k = 0; k < 3; k++)
-+ cb[k] *= (ds / as);
-+ glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-+ }
-+ }
-+ if (fl_mode == 2)
-+ glNormal3d (n(j,i,0), n(j,i,1), n(j,i,2));
-+ glVertex3d (x(j2,i), y(j,i2), z(j,i));
-+
-+ // Vertex 4
-+ if (fc_mode == 3)
-+ tex.tex_coord (double (i-1) / (zc-1), double (j) / (zr-1));
-+ else if (fc_mode == 2)
-+ {
-+ for (int k = 0; k < 3; k++)
-+ cb[k] = c(j, i-1, k);
-+ glColor3fv (cb);
-+
-+ if (fl_mode > 0)
-+ {
-+ for (int k = 0; k < 3; k++)
-+ cb[k] *= as;
-+ glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-+
-+ for (int k = 0; k < 3; k++)
-+ cb[k] *= (ds / as);
-+ glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-+ }
-+ }
-+ if (fl_mode == 2)
-+ glNormal3d (n(j,i-1,0), n(j,i-1,1), n(j,i-1,2));
-+ glVertex3d (x(j2,i-1), y(j,i1), z(j,i-1));
-+
-+ glEnd ();
-+ }
-+ }
-+
-+ set_polygon_offset (false);
-+ if (fc_mode == 3)
-+ glDisable (GL_TEXTURE_2D);
-+
-+ if (fl_mode > 0)
-+ glDisable (GL_LIGHTING);
-+ }
-+ else
-+ {
-+ // FIXME: implement transparency
-+ }
-+ }
-+
-+ if (! props.edgecolor_is ("none"))
-+ {
-+ if (props.get_edgealpha_double () == 1)
-+ {
-+ if (ec_mode == 0)
-+ {
-+ glColor3dv (ecolor.data ());
-+ if (fl_mode > 0)
-+ {
-+ for (int i = 0; i < 3; i++)
-+ cb[i] = (as * ecolor(i));
-+ glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-+
-+ for (int i = 0; i < 3; i++)
-+ cb[i] *= (ds / as);
-+ glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-+ }
-+ }
-+
-+ if (el_mode > 0)
-+ glEnable (GL_LIGHTING);
-+ glShadeModel ((ec_mode == 2 || el_mode == 2) ? GL_SMOOTH : GL_FLAT);
-+
-+ set_linestyle (props.get_linestyle (), false);
-+ set_linewidth (props.get_linewidth ());
-+
-+ // Mesh along Y-axis
-+
-+ if (props.meshstyle_is ("both") || props.meshstyle_is ("column"))
-+ {
-+ for (int i = 0; i < zc; i++)
-+ {
-+ if (y_mat)
-+ {
-+ i1 = i-1;
-+ i2 = i;
-+ }
-+
-+ for (int j = 1; j < zr; j++)
-+ {
-+ if (clip(j-1,i) || clip(j,i))
-+ continue;
-+
-+ if (x_mat)
-+ {
-+ j1 = j-1;
-+ j2 = j;
-+ }
-+
-+ glBegin (GL_LINES);
-+
-+ // Vertex 1
-+ if (ec_mode > 0)
-+ {
-+ for (int k = 0; k < 3; k++)
-+ cb[k] = c(j-1, i, k);
-+ glColor3fv (cb);
-+
-+ if (fl_mode > 0)
-+ {
-+ for (int k = 0; k < 3; k++)
-+ cb[k] *= as;
-+ glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-+
-+ for (int k = 0; k < 3; k++)
-+ cb[k] *= (ds / as);
-+ glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-+ }
-+ }
-+ if (el_mode > 0)
-+ glNormal3d (n(j-1,i,0), n(j-1,i,1), n(j-1,i,2));
-+ glVertex3d (x(j1,i), y(j-1,i2), z(j-1,i));
-+
-+ // Vertex 2
-+ if (ec_mode == 2)
-+ {
-+ for (int k = 0; k < 3; k++)
-+ cb[k] = c(j, i, k);
-+ glColor3fv (cb);
-+
-+ if (fl_mode > 0)
-+ {
-+ for (int k = 0; k < 3; k++)
-+ cb[k] *= as;
-+ glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-+
-+ for (int k = 0; k < 3; k++)
-+ cb[k] *= (ds / as);
-+ glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-+ }
-+ }
-+ if (el_mode == 2)
-+ glNormal3d (n(j,i,0), n(j,i,1), n(j,i,2));
-+ glVertex3d (x(j2,i), y(j,i2), z(j,i));
-+
-+ glEnd ();
-+ }
-+ }
-+ }
-+
-+ // Mesh along X-axis
-+
-+ if (props.meshstyle_is ("both") || props.meshstyle_is ("row"))
-+ {
-+ for (int j = 0; j < zr; j++)
-+ {
-+ if (x_mat)
-+ {
-+ j1 = j-1;
-+ j2 = j;
-+ }
-+
-+ for (int i = 1; i < zc; i++)
-+ {
-+ if (clip(j,i-1) || clip(j,i))
-+ continue;
-+
-+ if (y_mat)
-+ {
-+ i1 = i-1;
-+ i2 = i;
-+ }
-+
-+ glBegin (GL_LINES);
-+
-+ // Vertex 1
-+ if (ec_mode > 0)
-+ {
-+ for (int k = 0; k < 3; k++)
-+ cb[k] = c(j, i-1, k);
-+ glColor3fv (cb);
-+
-+ if (fl_mode > 0)
-+ {
-+ for (int k = 0; k < 3; k++)
-+ cb[k] *= as;
-+ glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-+
-+ for (int k = 0; k < 3; k++)
-+ cb[k] *= (ds / as);
-+ glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-+ }
-+ }
-+ if (el_mode > 0)
-+ glNormal3d (n(j,i-1,0), n(j,i-1,1), n(j,i-1,2));
-+ glVertex3d (x(j2,i-1), y(j,i1), z(j,i-1));
-+
-+ // Vertex 2
-+ if (ec_mode == 2)
-+ {
-+ for (int k = 0; k < 3; k++)
-+ cb[k] = c(j, i, k);
-+ glColor3fv (cb);
-+
-+ if (fl_mode > 0)
-+ {
-+ for (int k = 0; k < 3; k++)
-+ cb[k] *= as;
-+ glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-+
-+ for (int k = 0; k < 3; k++)
-+ cb[k] *= (ds / as);
-+ glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-+ }
-+ }
-+ if (el_mode == 2)
-+ glNormal3d (n(j,i,0), n(j,i,1), n(j,i,2));
-+ glVertex3d (x(j2,i), y(j,i2), z(j,i));
-+
-+ glEnd ();
-+ }
-+ }
-+ }
-+
-+ set_linestyle ("-");
-+ set_linewidth (0.5);
-+
-+ if (el_mode > 0)
-+ glDisable (GL_LIGHTING);
-+ }
-+ else
-+ {
-+ // FIXME: implement transparency
-+ }
-+ }
-+
-+ if (! props.marker_is ("none") &&
-+ ! (props.markeredgecolor_is ("none")
-+ && props.markerfacecolor_is ("none")))
-+ {
-+ // FIXME: check how transparency should be handled in markers
-+ // FIXME: check what to do with marker facecolor set to auto
-+ // and facecolor set to none.
-+
-+ bool do_edge = ! props.markeredgecolor_is ("none");
-+ bool do_face = ! props.markerfacecolor_is ("none");
-+
-+ Matrix mecolor = props.get_markeredgecolor_rgb ();
-+ Matrix mfcolor = props.get_markerfacecolor_rgb ();
-+ Matrix cc (1, 3, 0.0);
-+
-+ if (mecolor.numel () == 0 && props.markeredgecolor_is ("auto"))
-+ {
-+ mecolor = props.get_edgecolor_rgb ();
-+ do_edge = ! props.edgecolor_is ("none");
-+ }
-+
-+ if (mfcolor.numel () == 0 && props.markerfacecolor_is ("auto"))
-+ {
-+ mfcolor = props.get_facecolor_rgb ();
-+ do_face = ! props.facecolor_is ("none");
-+ }
-+
-+ if ((mecolor.numel () == 0 || mfcolor.numel () == 0)
-+ && c.numel () == 0)
-+ c = props.get_color_data ().array_value ();
-+
-+ init_marker (props.get_marker (), props.get_markersize (),
-+ props.get_linewidth ());
-+
-+ for (int i = 0; i < zc; i++)
-+ {
-+ if (y_mat)
-+ i1 = i;
-+
-+ for (int j = 0; j < zr; j++)
-+ {
-+ if (clip(j,i))
-+ continue;
-+
-+ if (x_mat)
-+ j1 = j;
-+
-+ if ((do_edge && mecolor.numel () == 0)
-+ || (do_face && mfcolor.numel () == 0))
-+ {
-+ for (int k = 0; k < 3; k++)
-+ cc(k) = c(j,i,k);
-+ }
-+
-+ Matrix lc = (do_edge ? (mecolor.numel () == 0 ? cc : mecolor) : Matrix ());
-+ Matrix fc = (do_face ? (mfcolor.numel () == 0 ? cc : mfcolor) : Matrix ());
-+
-+ draw_marker (x(j1,i), y(j,i1), z(j,i), lc, fc);
-+ }
-+ }
-+
-+ end_marker ();
-+ }
-+}
-+
-+// FIXME: global optimization (rendering, data structures...), there
-+// is probably a smarter/faster/less-memory-consuming way to do this.
-+void
-+opengl_renderer::draw (const patch::properties &props)
-+{
-+ Matrix f = props.get_faces ().matrix_value ();
-+ Matrix v = xform.scale (props.get_vertices ().matrix_value ());
-+ Matrix c;
-+ Matrix n = props.get_vertexnormals ().matrix_value ();
-+ Matrix a;
-+
-+ int nv = v.rows ();
-+ // int vmax = v.columns ();
-+ int nf = f.rows ();
-+ int fcmax = f.columns ();
-+
-+ bool has_z = (v.columns () > 2);
-+ bool has_facecolor = false;
-+ bool has_facealpha = false;
-+
-+ int fc_mode = (props.facecolor_is_rgb () ? 0 :
-+ (props.facecolor_is("flat") ? 1 : 2));
-+ int fl_mode = (props.facelighting_is ("none") ? 0 :
-+ (props.facelighting_is ("flat") ? 1 : 2));
-+ int fa_mode = (props.facealpha_is_double () ? 0 :
-+ (props.facealpha_is ("flat") ? 1 : 2));
-+ int ec_mode = (props.edgecolor_is_rgb () ? 0 :
-+ (props.edgecolor_is("flat") ? 1 : 2));
-+ int el_mode = (props.edgelighting_is ("none") ? 0 :
-+ (props.edgelighting_is ("flat") ? 1 : 2));
-+ int ea_mode = (props.edgealpha_is_double () ? 0 :
-+ (props.edgealpha_is ("flat") ? 1 : 2));
-+
-+ Matrix fcolor = props.get_facecolor_rgb ();
-+ Matrix ecolor = props.get_edgecolor_rgb ();
-+
-+ float as = props.get_ambientstrength ();
-+ float ds = props.get_diffusestrength ();
-+ float ss = props.get_specularstrength ();
-+ float se = props.get_specularexponent ();
-+
-+ boolMatrix clip (1, nv, false);
-+
-+ if (has_z)
-+ for (int i = 0; i < nv; i++)
-+ clip(i) = is_nan_or_inf (v(i,0), v(i,1), v(i,2));
-+ else
-+ for (int i = 0; i < nv; i++)
-+ clip(i) = is_nan_or_inf (v(i,0), v(i,1), 0);
-+
-+ boolMatrix clip_f (1, nf, false);
-+ Array<int> count_f (nf, 0);
-+
-+ for (int i = 0; i < nf; i++)
-+ {
-+ bool fclip = false;
-+ int count = 0;
-+
-+ for (int j = 0; j < fcmax && ! xisnan (f(i,j)); j++, count++)
-+ fclip = (fclip || clip(int (f(i,j) - 1)));
-+
-+ clip_f(i) = fclip;
-+ count_f(i) = count;
-+ }
-+
-+ if (fc_mode > 0 || ec_mode > 0)
-+ {
-+ c = props.get_color_data ().matrix_value ();
-+
-+ if (c.rows () == 1)
-+ {
-+ // Single color specifications, we can simplify a little bit
-+
-+ if (fc_mode > 0)
-+ {
-+ fcolor = c;
-+ fc_mode = 0;
-+ }
-+
-+ if (ec_mode > 0)
-+ {
-+ ecolor = c;
-+ ec_mode = 0;
-+ }
-+
-+ c = Matrix ();
-+ }
-+ else
-+ has_facecolor = ((c.numel () > 0) && (c.rows () == f.rows ()));
-+ }
-+
-+ if (fa_mode > 0 || ea_mode > 0)
-+ {
-+ // FIXME: retrieve alpha data from patch object
-+ //a = props.get_alpha_data ();
-+ has_facealpha = ((a.numel () > 0) && (a.rows () == f.rows ()));
-+ }
-+
-+ octave_idx_type fr = f.rows ();
-+ std::vector<vertex_data> vdata (f.numel ());
-+
-+ for (int i = 0; i < nf; i++)
-+ for (int j = 0; j < count_f(i); j++)
-+ {
-+ int idx = int (f(i,j) - 1);
-+
-+ Matrix vv (1, 3, 0.0);
-+ Matrix cc;
-+ Matrix nn(1, 3, 0.0);
-+ double aa = 1.0;
-+
-+ vv(0) = v(idx,0); vv(1) = v(idx,1);
-+ if (has_z)
-+ vv(2) = v(idx,2);
-+ // FIXME: uncomment when patch object has normal computation
-+ //nn(0) = n(idx,0); nn(1) = n(idx,1); nn(2) = n(idx,2);
-+ if (c.numel () > 0)
-+ {
-+ cc.resize (1, 3);
-+ if (has_facecolor)
-+ cc(0) = c(i,0), cc(1) = c(i,1), cc(2) = c(i,2);
-+ else
-+ cc(0) = c(idx,0), cc(1) = c(idx,1), cc(2) = c(idx,2);
-+ }
-+ if (a.numel () > 0)
-+ {
-+ if (has_facealpha)
-+ aa = a(i);
-+ else
-+ aa = a(idx);
-+ }
-+
-+ vdata[i+j*fr] =
-+ vertex_data (vv, cc, nn, aa, as, ds, ss, se);
-+ }
-+
-+ if (fl_mode > 0 || el_mode > 0)
-+ {
-+ float buf[4] = { ss, ss, ss, 1 };
-+
-+ glMaterialfv (LIGHT_MODE, GL_SPECULAR, buf);
-+ glMaterialf (LIGHT_MODE, GL_SHININESS, se);
-+ }
-+
-+ if (! props.facecolor_is ("none"))
-+ {
-+ // FIXME: adapt to double-radio property
-+ if (props.get_facealpha_double () == 1)
-+ {
-+ if (fc_mode == 0)
-+ {
-+ glColor3dv (fcolor.data ());
-+ if (fl_mode > 0)
-+ {
-+ float cb[4] = { 0, 0, 0, 1 };
-+
-+ for (int i = 0; i < 3; i++)
-+ cb[i] = (as * fcolor(i));
-+ glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-+
-+ for (int i = 0; i < 3; i++)
-+ cb[i] *= (ds / as);
-+ glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-+ }
-+ }
-+
-+ if (fl_mode > 0)
-+ glEnable (GL_LIGHTING);
-+
-+ // FIXME: use __index__ property from patch object
-+ patch_tesselator tess (this, fc_mode, fl_mode, 0);
-+
-+ for (int i = 0; i < nf; i++)
-+ {
-+ if (clip_f(i))
-+ continue;
-+
-+ tess.begin_polygon (true);
-+ tess.begin_contour ();
-+
-+ for (int j = 0; j < count_f(i); j++)
-+ {
-+ vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep ();
-+
-+ tess.add_vertex (vv->coords.fortran_vec (), vv);
-+ }
-+
-+ tess.end_contour ();
-+ tess.end_polygon ();
-+ }
-+
-+ if (fl_mode > 0)
-+ glDisable (GL_LIGHTING);
-+ }
-+ else
-+ {
-+ // FIXME: implement transparency
-+ }
-+ }
-+
-+ if (! props.edgecolor_is ("none"))
-+ {
-+ // FIXME: adapt to double-radio property
-+ if (props.get_edgealpha_double () == 1)
-+ {
-+ if (ec_mode == 0)
-+ {
-+ glColor3dv (ecolor.data ());
-+ if (el_mode > 0)
-+ {
-+ float cb[4] = { 0, 0, 0, 1 };
-+
-+ for (int i = 0; i < 3; i++)
-+ cb[i] = (as * ecolor(i));
-+ glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-+
-+ for (int i = 0; i < 3; i++)
-+ cb[i] *= (ds / as);
-+ glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-+ }
-+ }
-+
-+ if (el_mode > 0)
-+ glEnable (GL_LIGHTING);
-+
-+ set_linestyle (props.get_linestyle (), false);
-+ set_linewidth (props.get_linewidth ());
-+
-+ // FIXME: use __index__ property from patch object; should we
-+ // offset patch contour as well?
-+ patch_tesselator tess (this, ec_mode, el_mode);
-+
-+ for (int i = 0; i < nf; i++)
-+ {
-+ if (clip_f(i))
-+ continue;
-+
-+ tess.begin_polygon (false);
-+ tess.begin_contour ();
-+
-+ for (int j = 0; j < count_f(i); j++)
-+ {
-+ vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep ();
-+
-+ tess.add_vertex (vv->coords.fortran_vec (), vv);
-+ }
-+
-+ tess.end_contour ();
-+ tess.end_polygon ();
-+ }
-+
-+ set_linestyle ("-");
-+ set_linewidth (0.5);
-+
-+ if (el_mode > 0)
-+ glDisable (GL_LIGHTING);
-+ }
-+ else
-+ {
-+ // FIXME: implement transparency
-+ }
-+ }
-+
-+ if (! props.marker_is ("none") &&
-+ ! (props.markeredgecolor_is ("none") && props.markerfacecolor_is ("none")))
-+ {
-+ bool do_edge = ! props.markeredgecolor_is ("none");
-+ bool do_face = ! props.markerfacecolor_is ("none");
-+
-+ Matrix mecolor = props.get_markeredgecolor_rgb ();
-+ Matrix mfcolor = props.get_markerfacecolor_rgb ();
-+ Matrix cc (1, 3, 0.0);
-+
-+ if (mecolor.numel () == 0 && props.markeredgecolor_is ("auto"))
-+ {
-+ mecolor = props.get_edgecolor_rgb ();
-+ do_edge = ! props.edgecolor_is ("none");
-+ }
-+
-+ if (mfcolor.numel () == 0 && props.markerfacecolor_is ("auto"))
-+ {
-+ mfcolor = props.get_facecolor_rgb ();
-+ do_face = ! props.facecolor_is ("none");
-+ }
-+
-+ init_marker (props.get_marker (), props.get_markersize (),
-+ props.get_linewidth ());
-+
-+ for (int i = 0; i < nf; i++)
-+ for (int j = 0; j < count_f(i); j++)
-+ {
-+ int idx = int (f(i,j) - 1);
-+
-+ if (clip(idx))
-+ continue;
-+
-+ Matrix lc = (do_edge ? (mecolor.numel () == 0 ?
-+ vdata[i+j*fr].get_rep ()->color : mecolor)
-+ : Matrix ());
-+ Matrix fc = (do_face ? (mfcolor.numel () == 0 ?
-+ vdata[i+j*fr].get_rep ()->color : mfcolor)
-+ : Matrix ());
-+
-+ draw_marker (v(idx,0), v(idx,1), (has_z ? v(idx,2) : 0), lc, fc);
-+ }
-+
-+ end_marker ();
-+ }
-+}
-+
-+void
-+opengl_renderer::draw (const hggroup::properties &props)
-+{
-+ draw (props.get_children ());
-+}
-+
-+void
-+opengl_renderer::set_viewport (int w, int h)
-+{
-+ glViewport (0, 0, w, h);
-+}
-+
-+void
-+opengl_renderer::set_color (const Matrix& c)
-+{
-+ glColor3dv (c.data ());
-+}
-+
-+void
-+opengl_renderer::set_polygon_offset (bool on, double offset)
-+{
-+ if (on)
-+ {
-+ glPolygonOffset (offset, offset);
-+ glEnable (GL_POLYGON_OFFSET_FILL);
-+ glEnable (GL_POLYGON_OFFSET_LINE);
-+ }
-+ else
-+ {
-+ glDisable (GL_POLYGON_OFFSET_FILL);
-+ glDisable (GL_POLYGON_OFFSET_LINE);
-+ }
-+}
-+
-+void
-+opengl_renderer::set_linewidth (float w)
-+{
-+ glLineWidth (w);
-+}
-+
-+void
-+opengl_renderer::set_linestyle (const std::string& s, bool use_stipple)
-+{
-+ bool solid = false;
-+
-+ if (s == "-")
-+ {
-+ glLineStipple (1, static_cast<unsigned short> (0xFFFF));
-+ solid = true;
-+ }
-+ else if (s == ":")
-+ glLineStipple (1, static_cast<unsigned short> (0x8888));
-+ else if (s == "--")
-+ glLineStipple (1, static_cast<unsigned short> (0x0FFF));
-+ else if (s == "-.")
-+ glLineStipple (1, static_cast<unsigned short> (0x020F));
-+ else
-+ glLineStipple (1, static_cast<unsigned short> (0x0000));
-+
-+ if (solid && ! use_stipple)
-+ glDisable (GL_LINE_STIPPLE);
-+ else
-+ glEnable (GL_LINE_STIPPLE);
-+}
-+
-+void
-+opengl_renderer::set_clipbox (double x1, double x2, double y1, double y2,
-+ double z1, double z2)
-+{
-+ double dx = (x2-x1);
-+ double dy = (y2-y1);
-+ double dz = (z2-z1);
-+
-+ x1 -= 0.001*dx; x2 += 0.001*dx;
-+ y1 -= 0.001*dy; y2 += 0.001*dy;
-+ z1 -= 0.001*dz; z2 += 0.001*dz;
-+
-+ ColumnVector p (4, 0.0);
-+
-+ p(0) = -1; p(3) = x2;
-+ glClipPlane (GL_CLIP_PLANE0, p.data ());
-+ p(0) = 1; p(3) = -x1;
-+ glClipPlane (GL_CLIP_PLANE1, p.data ());
-+ p(0) = 0; p(1) = -1; p(3) = y2;
-+ glClipPlane (GL_CLIP_PLANE2, p.data ());
-+ p(1) = 1; p(3) = -y1;
-+ glClipPlane (GL_CLIP_PLANE3, p.data ());
-+ p(1) = 0; p(2) = -1; p(3) = z2;
-+ glClipPlane (GL_CLIP_PLANE4, p.data ());
-+ p(2) = 1; p(3) = -z1;
-+ glClipPlane (GL_CLIP_PLANE5, p.data ());
-+
-+ xmin = x1; xmax = x2;
-+ ymin = y1; ymax = y2;
-+ zmin = z1; zmax = z2;
-+}
-+
-+void
-+opengl_renderer::set_clipping (bool enable)
-+{
-+ bool has_clipping = (glIsEnabled (GL_CLIP_PLANE0) == GL_TRUE);
-+
-+ if (enable != has_clipping)
-+ {
-+ if (enable)
-+ for (int i = 0; i < 6; i++)
-+ glEnable (GL_CLIP_PLANE0+i);
-+ else
-+ for (int i = 0; i < 6; i++)
-+ glDisable (GL_CLIP_PLANE0+i);
-+ }
-+}
-+
-+void
-+opengl_renderer::init_marker (const std::string& m, double size, float width)
-+{
-+ int vw[4];
-+
-+ glGetIntegerv (GL_VIEWPORT, vw);
-+
-+ glMatrixMode (GL_PROJECTION);
-+ glPushMatrix ();
-+ glLoadIdentity ();
-+ glOrtho (0, vw[2], vw[3], 0, xZ1, xZ2);
-+ glMatrixMode (GL_MODELVIEW);
-+ glPushMatrix ();
-+
-+ set_clipping (false);
-+ set_linewidth (width);
-+
-+ marker_id = make_marker_list (m, size, false);
-+ filled_marker_id = make_marker_list (m, size, true);
-+}
-+
-+void
-+opengl_renderer::end_marker (void)
-+{
-+ glDeleteLists (marker_id, 1);
-+ glDeleteLists (filled_marker_id, 1);
-+
-+ glMatrixMode (GL_MODELVIEW);
-+ glPopMatrix ();
-+ glMatrixMode (GL_PROJECTION);
-+ glPopMatrix ();
-+ set_linewidth (0.5f);
-+}
-+
-+void
-+opengl_renderer::draw_marker (double x, double y, double z,
-+ const Matrix& lc, const Matrix& fc)
-+{
-+ ColumnVector tmp = xform.transform (x, y, z, false);
-+
-+ glLoadIdentity ();
-+ glTranslated (tmp(0), tmp(1), -tmp(2));
-+
-+ if (filled_marker_id > 0 && fc.numel () > 0)
-+ {
-+ glColor3dv (fc.data ());
-+ set_polygon_offset (true, -1.0);
-+ glCallList (filled_marker_id);
-+ if (lc.numel () > 0)
-+ {
-+ glColor3dv (lc.data ());
-+ glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
-+ glEdgeFlag (GL_TRUE);
-+ set_polygon_offset (true, -2.0);
-+ glCallList (filled_marker_id);
-+ glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
-+ }
-+ set_polygon_offset (false);
-+ }
-+ else if (marker_id > 0 && lc.numel () > 0)
-+ {
-+ glColor3dv (lc.data ());
-+ glCallList (marker_id);
-+ }
-+}
-+
-+unsigned int
-+opengl_renderer::make_marker_list (const std::string& marker, double size,
-+ bool filled) const
-+{
-+ char c = marker[0];
-+
-+ if (filled && (c == '+' || c == 'x' || c == '*' || c == '.'))
-+ return 0;
-+
-+ unsigned int ID = glGenLists (1);
-+ double sz = size * backend.get_screen_resolution () / 72.0;
-+
-+ // constants for the * marker
-+ const double sqrt2d4 = 0.35355339059327;
-+ double tt = sz*sqrt2d4;
-+
-+ glNewList (ID, GL_COMPILE);
-+
-+ switch (marker[0])
-+ {
-+ case '+':
-+ glBegin (GL_LINES);
-+ glVertex2f (-sz/2 ,0 );
-+ glVertex2f (sz/2 ,0 );
-+ glVertex2f (0 ,-sz/2 );
-+ glVertex2f (0 ,sz/2 );
-+ glEnd ();
-+ break;
-+ case 'x':
-+ glBegin(GL_LINES);
-+ glVertex2f (-sz/2 ,-sz/2);
-+ glVertex2f (sz/2 ,sz/2 );
-+ glVertex2f (-sz/2 ,sz/2 );
-+ glVertex2f (sz/2 ,-sz/2 );
-+ glEnd ();
-+ break;
-+ case '*':
-+ glBegin (GL_LINES);
-+ glVertex2f (-sz/2 ,0 );
-+ glVertex2f (sz/2 ,0 );
-+ glVertex2f (0 ,-sz/2 );
-+ glVertex2f (0 ,sz/2 );
-+ glVertex2f (-tt ,-tt );
-+ glVertex2f (+tt ,+tt );
-+ glVertex2f (-tt ,+tt );
-+ glVertex2f (+tt ,-tt );
-+ glEnd ();
-+ break;
-+ case '.':
-+ glBegin (GL_POLYGON);
-+ glVertex2f (-sz/10, -sz/10);
-+ glVertex2f (-sz/10, sz/10 );
-+ glVertex2f (sz/10 , sz/10 );
-+ glVertex2f (sz/10 , -sz/10);
-+ glEnd ();
-+ break;
-+ case 's':
-+ glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-+ glVertex2d (-sz/2, -sz/2);
-+ glVertex2d (-sz/2, sz/2);
-+ glVertex2d ( sz/2, sz/2);
-+ glVertex2d ( sz/2, -sz/2);
-+ glEnd();
-+ break;
-+ case 'o':
-+ {
-+ double ang_step = M_PI / 5;
-+
-+ glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-+ for (double ang = 0; ang < (2*M_PI); ang += ang_step)
-+ glVertex2d (sz*cos(ang)/2, sz*sin(ang)/2);
-+ glEnd ();
-+ }
-+ break;
-+ case 'd':
-+ glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-+ glVertex2d ( 0, -sz/2);
-+ glVertex2d ( sz/2, 0);
-+ glVertex2d ( 0, sz/2);
-+ glVertex2d (-sz/2, 0);
-+ glEnd();
-+ break;
-+ case '^':
-+ glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-+ glVertex2f (0 , sz/2);
-+ glVertex2f (sz/2 , -sz/2);
-+ glVertex2f (-sz/2 , -sz/2);
-+ glEnd ();
-+ break;
-+ case 'v':
-+ glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-+ glVertex2f (0 ,-sz/2);
-+ glVertex2f (-sz/2 ,sz/2 );
-+ glVertex2f (sz/2 ,sz/2 );
-+ glEnd ();
-+ break;
-+ case '>':
-+ glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-+ glVertex2f (sz/2 ,0 );
-+ glVertex2f (-sz/2 ,sz/2 );
-+ glVertex2f (-sz/2 ,-sz/2);
-+ glEnd ();
-+ break;
-+ case '<':
-+ glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-+ glVertex2f (-sz/2 ,0 );
-+ glVertex2f (sz/2 ,-sz/2);
-+ glVertex2f (sz/2 ,sz/2 );
-+ glEnd ();
-+ break;
-+ default:
-+ warning ("opengl_renderer: unsupported marker `%s'",
-+ marker.c_str ());
-+ break;
-+ }
-+
-+ glEndList ();
-+
-+ return ID;
-+}
-+
-+/*
-+;;; Local Variables: ***
-+;;; mode: C++ ***
-+;;; End: ***
-+*/
More information about the Pkg-octave-commit
mailing list