00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #if defined (HAVE_OPENGL)
00028
00029 #include <iostream>
00030
00031 #include <lo-mappers.h>
00032 #include "oct-locbuf.h"
00033 #include "oct-refcount.h"
00034 #include "gl-render.h"
00035 #include "txt-eng.h"
00036 #include "txt-eng-ft.h"
00037
00038 #define LIGHT_MODE GL_FRONT_AND_BACK
00039
00040
00041
00042
00043 #ifndef CALLBACK
00044 #define CALLBACK
00045 #endif
00046
00047 static octave_idx_type
00048 xmin (octave_idx_type x, octave_idx_type y)
00049 {
00050 return x < y ? x : y;
00051 }
00052
00053 class
00054 opengl_texture
00055 {
00056 protected:
00057 class texture_rep
00058 {
00059 public:
00060 texture_rep (void)
00061 : id (), w (), h (), tw (), th (), tx (), ty (),
00062 valid (false), count (1)
00063 { }
00064
00065 texture_rep (GLuint id_arg, int w_arg, int h_arg, int tw_arg, int th_arg)
00066 : id (id_arg), w (w_arg), h (h_arg), tw (tw_arg), th (th_arg),
00067 tx (double(w)/tw), ty (double(h)/th), valid (true),
00068 count (1) { }
00069
00070 ~texture_rep (void)
00071 {
00072 if (valid)
00073 glDeleteTextures (1, &id);
00074 }
00075
00076 void bind (int mode) const
00077 { if (valid) glBindTexture (mode, id); }
00078
00079 void tex_coord (double q, double r) const
00080 { if (valid) glTexCoord2d (q*tx, r*ty); }
00081
00082 GLuint id;
00083 int w, h;
00084 int tw, th;
00085 double tx, ty;
00086 bool valid;
00087 octave_refcount<int> count;
00088 };
00089
00090 texture_rep *rep;
00091
00092 private:
00093 opengl_texture (texture_rep *_rep) : rep (_rep) { }
00094
00095 public:
00096 opengl_texture (void) : rep (new texture_rep ()) { }
00097
00098 opengl_texture (const opengl_texture& tx)
00099 : rep (tx.rep)
00100 {
00101 rep->count++;
00102 }
00103
00104 ~opengl_texture (void)
00105 {
00106 if (--rep->count == 0)
00107 delete rep;
00108 }
00109
00110 opengl_texture& operator = (const opengl_texture& tx)
00111 {
00112 if (--rep->count == 0)
00113 delete rep;
00114
00115 rep = tx.rep;
00116 rep->count++;
00117
00118 return *this;
00119 }
00120
00121 static opengl_texture create (const octave_value& data);
00122
00123 void bind (int mode = GL_TEXTURE_2D) const
00124 { rep->bind (mode); }
00125
00126 void tex_coord (double q, double r) const
00127 { rep->tex_coord (q, r); }
00128
00129 bool is_valid (void) const
00130 { return rep->valid; }
00131 };
00132
00133 static int
00134 next_power_of_2 (int n)
00135 {
00136 int m = 1;
00137
00138 while (m < n && m < INT_MAX)
00139 m <<= 1;
00140
00141 return m;
00142 }
00143
00144 opengl_texture
00145 opengl_texture::create (const octave_value& data)
00146 {
00147 opengl_texture retval;
00148
00149 dim_vector dv (data.dims ());
00150
00151
00152 if (dv.length () == 3 && dv(2) == 3)
00153 {
00154
00155
00156 int h = dv(0), w = dv(1), tw, th;
00157 GLuint id;
00158 bool ok = true;
00159
00160 tw = next_power_of_2 (w);
00161 th = next_power_of_2 (w);
00162
00163 glGenTextures (1, &id);
00164 glBindTexture (GL_TEXTURE_2D, id);
00165
00166 if (data.is_double_type ())
00167 {
00168 const NDArray xdata = data.array_value ();
00169
00170 OCTAVE_LOCAL_BUFFER (float, a, (3*tw*th));
00171
00172 for (int i = 0; i < h; i++)
00173 {
00174 for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3)
00175 {
00176 a[idx] = xdata(i,j,0);
00177 a[idx+1] = xdata(i,j,1);
00178 a[idx+2] = xdata(i,j,2);
00179 }
00180 }
00181
00182 glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0,
00183 GL_RGB, GL_FLOAT, a);
00184 }
00185 else if (data.is_uint8_type ())
00186 {
00187 const uint8NDArray xdata = data.uint8_array_value ();
00188
00189 OCTAVE_LOCAL_BUFFER (octave_uint8, a, (3*tw*th));
00190
00191 for (int i = 0; i < h; i++)
00192 {
00193 for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3)
00194 {
00195 a[idx] = xdata(i,j,0);
00196 a[idx+1] = xdata(i,j,1);
00197 a[idx+2] = xdata(i,j,2);
00198 }
00199 }
00200
00201 glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0,
00202 GL_RGB, GL_UNSIGNED_BYTE, a);
00203 }
00204 else
00205 {
00206 ok = false;
00207 warning ("opengl_texture::create: invalid texture data type (expected double or uint8)");
00208 }
00209
00210 if (ok)
00211 {
00212 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00213 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00214
00215 if (glGetError () != GL_NO_ERROR)
00216 warning ("opengl_texture::create: OpenGL error while generating texture data");
00217 else
00218 retval = opengl_texture (new texture_rep (id, w, h, tw, th));
00219 }
00220 }
00221 else
00222 warning ("opengl_texture::create: invalid texture data size");
00223
00224 return retval;
00225 }
00226
00227 class
00228 opengl_tesselator
00229 {
00230 public:
00231 #if defined (HAVE_FRAMEWORK_OPENGL) && defined (HAVE_GLUTESSCALLBACK_THREEDOTS)
00232 typedef GLvoid (CALLBACK *fcn) (...);
00233 #else
00234 typedef void (CALLBACK *fcn) (void);
00235 #endif
00236
00237 public:
00238
00239 opengl_tesselator (void) : glu_tess (0), fill() { init (); }
00240
00241 virtual ~opengl_tesselator (void)
00242 { if (glu_tess) gluDeleteTess (glu_tess); }
00243
00244 void begin_polygon (bool filled = true)
00245 {
00246 gluTessProperty (glu_tess, GLU_TESS_BOUNDARY_ONLY,
00247 (filled ? GL_FALSE : GL_TRUE));
00248 fill = filled;
00249 gluTessBeginPolygon (glu_tess, this);
00250 }
00251
00252 void end_polygon (void) const
00253 { gluTessEndPolygon (glu_tess); }
00254
00255 void begin_contour (void) const
00256 { gluTessBeginContour (glu_tess); }
00257
00258 void end_contour (void) const
00259 { gluTessEndContour (glu_tess); }
00260
00261 void add_vertex (double *loc, void *data) const
00262 { gluTessVertex (glu_tess, loc, data); }
00263
00264 protected:
00265 virtual void begin (GLenum ) { }
00266
00267 virtual void end (void) { }
00268
00269 virtual void vertex (void *) { }
00270
00271 virtual void combine (GLdouble [3], void *[4],
00272 GLfloat [4], void **) { }
00273
00274 virtual void edge_flag (GLboolean ) { }
00275
00276 virtual void error (GLenum err)
00277 { ::error ("OpenGL tesselation error (%d)", err); }
00278
00279 virtual void init (void)
00280 {
00281 glu_tess = gluNewTess ();
00282
00283 gluTessCallback (glu_tess, GLU_TESS_BEGIN_DATA,
00284 reinterpret_cast<fcn> (tess_begin));
00285 gluTessCallback (glu_tess, GLU_TESS_END_DATA,
00286 reinterpret_cast<fcn> (tess_end));
00287 gluTessCallback (glu_tess, GLU_TESS_VERTEX_DATA,
00288 reinterpret_cast<fcn> (tess_vertex));
00289 gluTessCallback (glu_tess, GLU_TESS_COMBINE_DATA,
00290 reinterpret_cast<fcn> (tess_combine));
00291 gluTessCallback (glu_tess, GLU_TESS_EDGE_FLAG_DATA,
00292 reinterpret_cast<fcn> (tess_edge_flag));
00293 gluTessCallback (glu_tess, GLU_TESS_ERROR_DATA,
00294 reinterpret_cast<fcn> (tess_error));
00295 }
00296
00297 bool is_filled (void) const { return fill; }
00298
00299 private:
00300 static void CALLBACK tess_begin (GLenum type, void *t)
00301 { reinterpret_cast<opengl_tesselator *> (t)->begin (type); }
00302
00303 static void CALLBACK tess_end (void *t)
00304 { reinterpret_cast<opengl_tesselator *> (t)->end (); }
00305
00306 static void CALLBACK tess_vertex (void *v, void *t)
00307 { reinterpret_cast<opengl_tesselator *> (t)->vertex (v); }
00308
00309 static void CALLBACK tess_combine (GLdouble c[3], void *v[4], GLfloat w[4],
00310 void **out, void *t)
00311 { reinterpret_cast<opengl_tesselator *> (t)->combine (c, v, w, out); }
00312
00313 static void CALLBACK tess_edge_flag (GLboolean flag, void *t)
00314 { reinterpret_cast<opengl_tesselator *> (t)->edge_flag (flag); }
00315
00316 static void CALLBACK tess_error (GLenum err, void *t)
00317 { reinterpret_cast<opengl_tesselator *> (t)->error (err); }
00318
00319 private:
00320
00321
00322
00323 opengl_tesselator (const opengl_tesselator&);
00324
00325 opengl_tesselator operator = (const opengl_tesselator&);
00326
00327 GLUtesselator *glu_tess;
00328 bool fill;
00329 };
00330
00331 class
00332 vertex_data
00333 {
00334 public:
00335 class vertex_data_rep
00336 {
00337 public:
00338 Matrix coords;
00339 Matrix color;
00340 Matrix normal;
00341 double alpha;
00342 float ambient;
00343 float diffuse;
00344 float specular;
00345 float specular_exp;
00346
00347
00348 octave_refcount<int> count;
00349
00350 vertex_data_rep (void)
00351 : coords (), color (), normal (), alpha (),
00352 ambient (), diffuse (), specular (), specular_exp (),count (1) { }
00353
00354 vertex_data_rep (const Matrix& c, const Matrix& col, const Matrix& n,
00355 double a, float as, float ds, float ss, float se)
00356 : coords (c), color (col), normal (n), alpha (a),
00357 ambient (as), diffuse (ds), specular (ss), specular_exp (se),
00358 count (1) { }
00359 };
00360
00361 private:
00362 vertex_data_rep *rep;
00363
00364 vertex_data_rep *nil_rep (void) const
00365 {
00366 static vertex_data_rep *nr = new vertex_data_rep ();
00367
00368 return nr;
00369 }
00370
00371 public:
00372 vertex_data (void) : rep (nil_rep ())
00373 { rep->count++; }
00374
00375 vertex_data (const vertex_data& v) : rep (v.rep)
00376 { rep->count++; }
00377
00378 vertex_data (const Matrix& c, const Matrix& col, const Matrix& n,
00379 double a, float as, float ds, float ss, float se)
00380 : rep (new vertex_data_rep (c, col, n, a, as, ds, ss, se))
00381 { }
00382
00383 vertex_data (vertex_data_rep *new_rep)
00384 : rep (new_rep) { }
00385
00386 ~vertex_data (void)
00387 {
00388 if (--rep->count == 0)
00389 delete rep;
00390 }
00391
00392 vertex_data& operator = (const vertex_data& v)
00393 {
00394 if (--rep->count == 0)
00395 delete rep;
00396
00397 rep = v.rep;
00398 rep->count++;
00399
00400 return *this;
00401 }
00402
00403 vertex_data_rep *get_rep (void) const { return rep; }
00404 };
00405
00406 class
00407 opengl_renderer::patch_tesselator : public opengl_tesselator
00408 {
00409 public:
00410 patch_tesselator (opengl_renderer *r, int cmode, int lmode, int idx = 0)
00411 : opengl_tesselator (), renderer (r),
00412 color_mode (cmode), light_mode (lmode), index (idx),
00413 first (true), tmp_vdata ()
00414 { }
00415
00416 protected:
00417 void begin (GLenum type)
00418 {
00419
00420 first = true;
00421
00422 if (color_mode == 2 || light_mode == 2)
00423 glShadeModel (GL_SMOOTH);
00424 else
00425 glShadeModel (GL_FLAT);
00426
00427 if (is_filled ())
00428 renderer->set_polygon_offset (true, 1+index);
00429
00430 glBegin (type);
00431 }
00432
00433 void end (void)
00434 {
00435
00436 glEnd ();
00437 renderer->set_polygon_offset (false);
00438 }
00439
00440 void vertex (void *data)
00441 {
00442 vertex_data::vertex_data_rep *v
00443 = reinterpret_cast<vertex_data::vertex_data_rep *> (data);
00444
00445
00446
00447
00448
00449
00450
00451 if (color_mode > 0 && (first || color_mode == 2))
00452 {
00453 Matrix col = v->color;
00454
00455 if (col.numel () == 3)
00456 {
00457 glColor3dv (col.data ());
00458 if (light_mode > 0)
00459 {
00460 float buf[4] = { 0, 0, 0, 1 };
00461
00462 for (int k = 0; k < 3; k++)
00463 buf[k] = (v->ambient * col(k));
00464 glMaterialfv (LIGHT_MODE, GL_AMBIENT, buf);
00465
00466 for (int k = 0; k < 3; k++)
00467 buf[k] = (v->diffuse * col(k));
00468 glMaterialfv (LIGHT_MODE, GL_AMBIENT, buf);
00469 }
00470 }
00471 }
00472
00473 if (light_mode > 0 && (first || light_mode == 2))
00474 glNormal3dv (v->normal.data ());
00475
00476 glVertex3dv (v->coords.data ());
00477
00478 first = false;
00479 }
00480
00481 void combine (GLdouble xyz[3], void *data[4], GLfloat w[4],
00482 void **out_data)
00483 {
00484
00485
00486 vertex_data::vertex_data_rep *v[4];
00487 int vmax = 4;
00488
00489 for (int i = 0; i < 4; i++)
00490 {
00491 v[i] = reinterpret_cast<vertex_data::vertex_data_rep *> (data[i]);
00492
00493 if (vmax == 4 && ! v[i])
00494 vmax = i;
00495 }
00496
00497 Matrix vv (1, 3, 0.0);
00498 Matrix cc;
00499 Matrix nn (1, 3, 0.0);
00500 double aa = 0.0;
00501
00502 vv(0) = xyz[0];
00503 vv(1) = xyz[1];
00504 vv(2) = xyz[2];
00505
00506 if (v[0]->color.numel ())
00507 {
00508 cc.resize (1, 3, 0.0);
00509 for (int ic = 0; ic < 3; ic++)
00510 for (int iv = 0; iv < vmax; iv++)
00511 cc(ic) += (w[iv] * v[iv]->color(ic));
00512 }
00513
00514 if (v[0]->normal.numel () > 0)
00515 {
00516 for (int in = 0; in < 3; in++)
00517 for (int iv = 0; iv < vmax; iv++)
00518 nn(in) += (w[iv] * v[iv]->normal(in));
00519 }
00520
00521 for (int iv = 0; iv < vmax; iv++)
00522 aa += (w[iv] * v[iv]->alpha);
00523
00524 vertex_data new_v (vv, cc, nn, aa, v[0]->ambient, v[0]->diffuse,
00525 v[0]->specular, v[0]->specular_exp);
00526 tmp_vdata.push_back (new_v);
00527
00528 *out_data = new_v.get_rep ();
00529 }
00530
00531 private:
00532
00533
00534
00535 patch_tesselator (const patch_tesselator&);
00536
00537 patch_tesselator& operator = (const patch_tesselator&);
00538
00539 opengl_renderer *renderer;
00540 int color_mode;
00541 int light_mode;
00542 int index;
00543 bool first;
00544 std::list<vertex_data> tmp_vdata;
00545 };
00546
00547 void
00548 opengl_renderer::draw (const graphics_object& go, bool toplevel)
00549 {
00550 if (! go.valid_object ())
00551 return;
00552
00553 const base_properties& props = go.get_properties ();
00554
00555 if (go.isa ("figure"))
00556 draw_figure (dynamic_cast<const figure::properties&> (props));
00557 else if (go.isa ("axes"))
00558 draw_axes (dynamic_cast<const axes::properties&> (props));
00559 else if (go.isa ("line"))
00560 draw_line (dynamic_cast<const line::properties&> (props));
00561 else if (go.isa ("surface"))
00562 draw_surface (dynamic_cast<const surface::properties&> (props));
00563 else if (go.isa ("patch"))
00564 draw_patch (dynamic_cast<const patch::properties&> (props));
00565 else if (go.isa ("hggroup"))
00566 draw_hggroup (dynamic_cast<const hggroup::properties&> (props));
00567 else if (go.isa ("text"))
00568 draw_text (dynamic_cast<const text::properties&> (props));
00569 else if (go.isa ("image"))
00570 draw_image (dynamic_cast<const image::properties&> (props));
00571 else if (go.isa ("uimenu") || go.isa ("uicontrol")
00572 || go.isa ("uicontextmenu") || go.isa ("uitoolbar")
00573 || go.isa ("uipushtool") || go.isa ("uitoggletool"))
00574 ;
00575 else if (go.isa ("uipanel"))
00576 {
00577 if (toplevel)
00578 draw_uipanel (dynamic_cast<const uipanel::properties&> (props), go);
00579 }
00580 else
00581 {
00582 warning ("opengl_renderer: cannot render object of type '%s'",
00583 props.graphics_object_name ().c_str ());
00584 }
00585 }
00586
00587 void
00588 opengl_renderer::draw_figure (const figure::properties& props)
00589 {
00590 toolkit = props.get_toolkit ();
00591
00592
00593
00594 init_gl_context (props.is___enhanced__ (), props.get_color_rgb ());
00595
00596
00597
00598 draw (props.get_all_children (), false);
00599 }
00600
00601 void
00602 opengl_renderer::draw_uipanel (const uipanel::properties& props,
00603 const graphics_object& go)
00604 {
00605 graphics_object fig = go.get_ancestor ("figure");
00606 const figure::properties& figProps =
00607 dynamic_cast<const figure::properties&> (fig.get_properties ());
00608
00609 toolkit = figProps.get_toolkit ();
00610
00611
00612
00613 init_gl_context (figProps.is___enhanced__ (),
00614 props.get_backgroundcolor_rgb ());
00615
00616
00617
00618 draw (props.get_all_children (), false);
00619 }
00620
00621 void
00622 opengl_renderer::init_gl_context (bool enhanced, const Matrix& c)
00623 {
00624
00625
00626 glEnable (GL_DEPTH_TEST);
00627 glDepthFunc (GL_LEQUAL);
00628 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00629 glAlphaFunc (GL_GREATER, 0.0f);
00630 glEnable (GL_NORMALIZE);
00631
00632 if (enhanced)
00633 {
00634 glEnable (GL_BLEND);
00635 glEnable (GL_LINE_SMOOTH);
00636 }
00637 else
00638 {
00639 glDisable (GL_BLEND);
00640 glDisable (GL_LINE_SMOOTH);
00641 }
00642
00643
00644
00645 if (c.length() >= 3)
00646 {
00647 glClearColor (c(0), c(1), c(2), 1);
00648 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00649 }
00650 }
00651
00652 void
00653 opengl_renderer::render_grid (const std::string& gridstyle,
00654 const Matrix& ticks, double lim1, double lim2,
00655 double p1, double p1N, double p2, double p2N,
00656 int xyz, bool is_3D)
00657 {
00658 set_linestyle (gridstyle, true);
00659 glBegin (GL_LINES);
00660 for (int i = 0; i < ticks.numel (); i++)
00661 {
00662 double val = ticks(i);
00663 if (lim1 <= val && val <= lim2)
00664 {
00665 if (xyz == 0)
00666 {
00667 glVertex3d (val, p1N, p2);
00668 glVertex3d (val, p1, p2);
00669 if (is_3D)
00670 {
00671 glVertex3d (val, p1, p2N);
00672 glVertex3d (val, p1, p2);
00673 }
00674 }
00675 else if (xyz == 1)
00676 {
00677 glVertex3d (p1N, val, p2);
00678 glVertex3d (p1, val, p2);
00679 if (is_3D)
00680 {
00681 glVertex3d (p1, val, p2N);
00682 glVertex3d (p1, val, p2);
00683 }
00684 }
00685 else if (xyz == 2)
00686 {
00687 glVertex3d (p1N, p2, val);
00688 glVertex3d (p1, p2, val);
00689 glVertex3d (p1, p2N, val);
00690 glVertex3d (p1, p2, val);
00691 }
00692 }
00693 }
00694 glEnd ();
00695 set_linestyle ("-", true);
00696 }
00697
00698 void
00699 opengl_renderer::render_tickmarks (const Matrix& ticks,
00700 double lim1, double lim2,
00701 double p1, double p1N,
00702 double p2, double p2N,
00703 double dx, double dy, double dz,
00704 int xyz, bool mirror)
00705 {
00706 glBegin (GL_LINES);
00707
00708 for (int i = 0; i < ticks.numel (); i++)
00709 {
00710 double val = ticks(i);
00711
00712 if (lim1 <= val && val <= lim2)
00713 {
00714 if (xyz == 0)
00715 {
00716 glVertex3d (val, p1, p2);
00717 glVertex3d (val, p1+dy, p2+dz);
00718 if (mirror)
00719 {
00720 glVertex3d (val, p1N, p2N);
00721 glVertex3d (val, p1N-dy, p2N-dz);
00722 }
00723 }
00724 else if (xyz == 1)
00725 {
00726 glVertex3d (p1, val, p2);
00727 glVertex3d (p1+dx, val, p2+dz);
00728 if (mirror)
00729 {
00730 glVertex3d (p1N, val, p2N);
00731 glVertex3d (p1N-dx, val, p2N-dz);
00732 }
00733 }
00734 else if (xyz == 2)
00735 {
00736 glVertex3d (p1, p2, val);
00737 glVertex3d (p1+dx, p2+dy, val);
00738 if (mirror)
00739 {
00740 glVertex3d (p1N, p2N, val);
00741 glVertex3d (p1N-dx, p2N-dy, val);
00742 }
00743 }
00744 }
00745 }
00746
00747 glEnd ();
00748 }
00749
00750 void
00751 opengl_renderer::render_ticktexts (const Matrix& ticks,
00752 const string_vector& ticklabels,
00753 double lim1, double lim2,
00754 double p1, double p2,
00755 int xyz, int ha, int va,
00756 int& wmax, int& hmax)
00757 {
00758 int n = std::min (ticklabels.numel (), ticks.numel ());
00759
00760 for (int i = 0; i < n; i++)
00761 {
00762 double val = ticks(i);
00763
00764 if (lim1 <= val && val <= lim2)
00765 {
00766 Matrix b;
00767
00768
00769 if (xyz == 0)
00770 {
00771 b = render_text (ticklabels(i), val, p1, p2, ha, va);
00772 }
00773 else if (xyz == 1)
00774 {
00775 b = render_text (ticklabels(i), p1, val, p2, ha, va);
00776 }
00777 else if (xyz == 2)
00778 {
00779 b = render_text (ticklabels(i), p1, p2, val, ha, va);
00780 }
00781
00782 wmax = std::max (wmax, static_cast<int> (b(2)));
00783 hmax = std::max (hmax, static_cast<int> (b(3)));
00784 }
00785 }
00786 }
00787
00788 void
00789 opengl_renderer::setup_opengl_transformation (const axes::properties& props)
00790 {
00791
00792
00793 Matrix x_zlim = props.get_transform_zlim ();
00794
00795 xZ1 = x_zlim(0)-(x_zlim(1)-x_zlim(0))/2;
00796 xZ2 = x_zlim(1)+(x_zlim(1)-x_zlim(0))/2;
00797
00798 Matrix x_mat1 = props.get_opengl_matrix_1 ();
00799 Matrix x_mat2 = props.get_opengl_matrix_2 ();
00800
00801 #if defined (HAVE_FRAMEWORK_OPENGL)
00802 GLint vw[4];
00803 #else
00804 int vw[4];
00805 #endif
00806
00807 glGetIntegerv (GL_VIEWPORT, vw);
00808
00809 glMatrixMode (GL_MODELVIEW);
00810 glLoadIdentity ();
00811 glScaled(1, 1, -1);
00812 glMultMatrixd (x_mat1.data ());
00813 glMatrixMode (GL_PROJECTION);
00814 glLoadIdentity ();
00815 glOrtho (0, vw[2], vw[3], 0, xZ1, xZ2);
00816 glMultMatrixd (x_mat2.data ());
00817 glMatrixMode (GL_MODELVIEW);
00818
00819 glClear (GL_DEPTH_BUFFER_BIT);
00820
00821 glDisable (GL_LINE_SMOOTH);
00822
00823
00824
00825 xform = props.get_transform ();
00826 }
00827
00828 void
00829 opengl_renderer::draw_axes_planes (const axes::properties& props)
00830 {
00831 double xPlane = props.get_xPlane ();
00832 double yPlane = props.get_yPlane ();
00833 double zPlane = props.get_zPlane ();
00834 double xPlaneN = props.get_xPlaneN ();
00835 double yPlaneN = props.get_yPlaneN ();
00836 double zPlaneN = props.get_zPlaneN ();
00837
00838
00839 Matrix axe_color = props.get_color_rgb ();
00840 if (axe_color.numel () > 0 && props.is_visible ())
00841 {
00842 set_color (axe_color);
00843 set_polygon_offset (true, 2.5);
00844
00845 glBegin (GL_QUADS);
00846
00847
00848 glVertex3d (xPlane, yPlaneN, zPlaneN);
00849 glVertex3d (xPlane, yPlane, zPlaneN);
00850 glVertex3d (xPlane, yPlane, zPlane);
00851 glVertex3d (xPlane, yPlaneN, zPlane);
00852
00853
00854 glVertex3d (xPlaneN, yPlane, zPlaneN);
00855 glVertex3d (xPlane, yPlane, zPlaneN);
00856 glVertex3d (xPlane, yPlane, zPlane);
00857 glVertex3d (xPlaneN, yPlane, zPlane);
00858
00859
00860 glVertex3d (xPlaneN, yPlaneN, zPlane);
00861 glVertex3d (xPlane, yPlaneN, zPlane);
00862 glVertex3d (xPlane, yPlane, zPlane);
00863 glVertex3d (xPlaneN, yPlane, zPlane);
00864
00865 glEnd ();
00866
00867 set_polygon_offset (false);
00868 }
00869 }
00870
00871 void
00872 opengl_renderer::draw_axes_boxes (const axes::properties& props)
00873 {
00874 bool xySym = props.get_xySym ();
00875 double xPlane = props.get_xPlane ();
00876 double yPlane = props.get_yPlane ();
00877 double zPlane = props.get_zPlane ();
00878 double xPlaneN = props.get_xPlaneN ();
00879 double yPlaneN = props.get_yPlaneN ();
00880 double zPlaneN = props.get_zPlaneN ();
00881 double xpTick = props.get_xpTick ();
00882 double ypTick = props.get_ypTick ();
00883 double zpTick = props.get_zpTick ();
00884 double xpTickN = props.get_xpTickN ();
00885 double ypTickN = props.get_ypTickN ();
00886 double zpTickN = props.get_zpTickN ();
00887
00888 bool plotyy = (props.has_property ("__plotyy_axes__"));
00889
00890
00891
00892 set_linestyle ("-", true);
00893 set_linewidth (props.get_linewidth ());
00894
00895 if (props.is_visible ())
00896 {
00897 glBegin (GL_LINES);
00898
00899
00900 set_color (props.get_xcolor_rgb ());
00901 glVertex3d (xPlaneN, ypTick, zpTick);
00902 glVertex3d (xPlane, ypTick, zpTick);
00903
00904 if (props.is_box ())
00905 {
00906 glVertex3d (xPlaneN, ypTickN, zpTick);
00907 glVertex3d (xPlane, ypTickN, zpTick);
00908 glVertex3d (xPlaneN, ypTickN, zpTickN);
00909 glVertex3d (xPlane, ypTickN, zpTickN);
00910 glVertex3d (xPlaneN, ypTick, zpTickN);
00911 glVertex3d (xPlane, ypTick, zpTickN);
00912 }
00913
00914
00915 set_color (props.get_ycolor_rgb ());
00916 glVertex3d (xpTick, yPlaneN, zpTick);
00917 glVertex3d (xpTick, yPlane, zpTick);
00918
00919 if (props.is_box () && ! plotyy)
00920 {
00921 glVertex3d (xpTickN, yPlaneN, zpTick);
00922 glVertex3d (xpTickN, yPlane, zpTick);
00923 glVertex3d (xpTickN, yPlaneN, zpTickN);
00924 glVertex3d (xpTickN, yPlane, zpTickN);
00925 glVertex3d (xpTick, yPlaneN, zpTickN);
00926 glVertex3d (xpTick, yPlane, zpTickN);
00927 }
00928
00929
00930 set_color (props.get_zcolor_rgb ());
00931
00932 if (xySym)
00933 {
00934 glVertex3d (xPlaneN, yPlane, zPlaneN);
00935 glVertex3d (xPlaneN, yPlane, zPlane);
00936 }
00937 else
00938 {
00939 glVertex3d (xPlane, yPlaneN, zPlaneN);
00940 glVertex3d (xPlane, yPlaneN, zPlane);
00941 }
00942
00943 if (props.is_box ())
00944 {
00945 glVertex3d (xPlane, yPlane, zPlaneN);
00946 glVertex3d (xPlane, yPlane, zPlane);
00947
00948 if (xySym)
00949 {
00950 glVertex3d (xPlane, yPlaneN, zPlaneN);
00951 glVertex3d (xPlane, yPlaneN, zPlane);
00952 }
00953 else
00954 {
00955 glVertex3d (xPlaneN, yPlane, zPlaneN);
00956 glVertex3d (xPlaneN, yPlane, zPlane);
00957 }
00958
00959 glVertex3d (xPlaneN, yPlaneN, zPlaneN);
00960 glVertex3d (xPlaneN, yPlaneN, zPlane);
00961 }
00962
00963 glEnd ();
00964 }
00965 }
00966
00967 void
00968 opengl_renderer::draw_axes_x_grid (const axes::properties& props)
00969 {
00970 int xstate = props.get_xstate ();
00971 int zstate = props.get_zstate ();
00972 bool x2Dtop = props.get_x2Dtop ();
00973 bool layer2Dtop = props.get_layer2Dtop ();
00974 bool xyzSym = props.get_xyzSym ();
00975 bool nearhoriz = props.get_nearhoriz ();
00976 double xticklen = props.get_xticklen ();
00977 double xtickoffset = props.get_xtickoffset ();
00978 double fy = props.get_fy ();
00979 double fz = props.get_fz ();
00980 double x_min = props.get_x_min ();
00981 double x_max = props.get_x_max ();
00982 double yPlane = props.get_yPlane ();
00983 double yPlaneN = props.get_yPlaneN ();
00984 double ypTick = props.get_ypTick ();
00985 double ypTickN = props.get_ypTickN ();
00986 double zPlane = props.get_zPlane ();
00987 double zPlaneN = props.get_zPlaneN ();
00988 double zpTick = props.get_zpTick ();
00989 double zpTickN = props.get_zpTickN ();
00990
00991
00992
00993 if (props.is_visible () && xstate != AXE_DEPTH_DIR)
00994 {
00995 std::string gridstyle = props.get_gridlinestyle ();
00996 std::string minorgridstyle = props.get_minorgridlinestyle ();
00997 bool do_xgrid = (props.is_xgrid () && (gridstyle != "none"));
00998 bool do_xminorgrid = (props.is_xminorgrid () && (minorgridstyle != "none"));
00999 bool do_xminortick = props.is_xminortick ();
01000 Matrix xticks = xform.xscale (props.get_xtick ().matrix_value ());
01001 Matrix xmticks = xform.xscale (props.get_xmtick ().matrix_value ());
01002 string_vector xticklabels = props.get_xticklabel ().all_strings ();
01003 int wmax = 0, hmax = 0;
01004 bool tick_along_z = nearhoriz || xisinf (fy);
01005 bool mirror = props.is_box () && xstate != AXE_ANY_DIR;
01006
01007 set_color (props.get_xcolor_rgb ());
01008
01009
01010 if (do_xgrid)
01011 render_grid (gridstyle, xticks, x_min, x_max,
01012 yPlane, yPlaneN, layer2Dtop ? zPlaneN : zPlane,
01013 zPlaneN, 0, (zstate != AXE_DEPTH_DIR));
01014
01015
01016 if (tick_along_z)
01017 {
01018 render_tickmarks (xticks, x_min, x_max, ypTick, ypTick,
01019 zpTick, zpTickN, 0., 0.,
01020 signum(zpTick-zpTickN)*fz*xticklen,
01021 0, mirror);
01022 }
01023 else
01024 {
01025 render_tickmarks (xticks, x_min, x_max, ypTick, ypTickN,
01026 zpTick, zpTick, 0.,
01027 signum(ypTick-ypTickN)*fy*xticklen,
01028 0., 0, mirror);
01029 }
01030
01031
01032 if (xticklabels.numel () > 0)
01033 {
01034 int halign = (xstate == AXE_HORZ_DIR ? 1 : (xyzSym ? 0 : 2));
01035 int valign = (xstate == AXE_VERT_DIR ? 1 : (x2Dtop ? 0 : 2));
01036
01037 if (tick_along_z)
01038 render_ticktexts (xticks, xticklabels, x_min, x_max, ypTick,
01039 zpTick+signum(zpTick-zpTickN)*fz*xtickoffset,
01040 0, halign, valign, wmax, hmax);
01041 else
01042 render_ticktexts (xticks, xticklabels, x_min, x_max,
01043 ypTick+signum(ypTick-ypTickN)*fy*xtickoffset,
01044 zpTick, 0, halign, valign, wmax, hmax);
01045 }
01046
01047
01048 if (do_xminorgrid)
01049 render_grid (minorgridstyle, xmticks, x_min, x_max,
01050 yPlane, yPlaneN, layer2Dtop ? zPlaneN : zPlane,
01051 zPlaneN, 0, (zstate != AXE_DEPTH_DIR));
01052
01053
01054 if (do_xminortick)
01055 {
01056 if (tick_along_z)
01057 render_tickmarks (xmticks, x_min, x_max, ypTick, ypTick,
01058 zpTick, zpTickN, 0., 0.,
01059 signum(zpTick-zpTickN)*fz*xticklen/2,
01060 0, mirror);
01061 else
01062 render_tickmarks (xmticks, x_min, x_max, ypTick, ypTickN,
01063 zpTick, zpTick, 0.,
01064 signum(ypTick-ypTickN)*fy*xticklen/2,
01065 0., 0, mirror);
01066 }
01067
01068 gh_manager::get_object (props.get_xlabel ()).set ("visible", "on");
01069 }
01070 else
01071 gh_manager::get_object (props.get_xlabel ()).set ("visible", "off");
01072 }
01073
01074 void
01075 opengl_renderer::draw_axes_y_grid (const axes::properties& props)
01076 {
01077 int ystate = props.get_ystate ();
01078 int zstate = props.get_zstate ();
01079 bool y2Dright = props.get_y2Dright ();
01080 bool layer2Dtop = props.get_layer2Dtop ();
01081 bool xyzSym = props.get_xyzSym ();
01082 bool nearhoriz = props.get_nearhoriz ();
01083 double yticklen = props.get_yticklen ();
01084 double ytickoffset = props.get_ytickoffset ();
01085 double fx = props.get_fx ();
01086 double fz = props.get_fz ();
01087 double xPlane = props.get_xPlane ();
01088 double xPlaneN = props.get_xPlaneN ();
01089 double xpTick = props.get_xpTick ();
01090 double xpTickN = props.get_xpTickN ();
01091 double y_min = props.get_y_min ();
01092 double y_max = props.get_y_max ();
01093 double zPlane = props.get_zPlane ();
01094 double zPlaneN = props.get_zPlaneN ();
01095 double zpTick = props.get_zpTick ();
01096 double zpTickN = props.get_zpTickN ();
01097
01098
01099
01100 if (ystate != AXE_DEPTH_DIR && props.is_visible ())
01101 {
01102 std::string gridstyle = props.get_gridlinestyle ();
01103 std::string minorgridstyle = props.get_minorgridlinestyle ();
01104 bool do_ygrid = (props.is_ygrid () && (gridstyle != "none"));
01105 bool do_yminorgrid = (props.is_yminorgrid () && (minorgridstyle != "none"));
01106 bool do_yminortick = props.is_yminortick ();
01107 Matrix yticks = xform.yscale (props.get_ytick ().matrix_value ());
01108 Matrix ymticks = xform.yscale (props.get_ymtick ().matrix_value ());
01109 string_vector yticklabels = props.get_yticklabel ().all_strings ();
01110 int wmax = 0, hmax = 0;
01111 bool tick_along_z = nearhoriz || xisinf (fx);
01112 bool mirror = props.is_box () && ystate != AXE_ANY_DIR
01113 && (! props.has_property ("__plotyy_axes__"));
01114
01115 set_color (props.get_ycolor_rgb ());
01116
01117
01118 if (do_ygrid)
01119 render_grid (gridstyle, yticks, y_min, y_max,
01120 xPlane, xPlaneN, layer2Dtop ? zPlaneN : zPlane,
01121 zPlaneN, 1, (zstate != AXE_DEPTH_DIR));
01122
01123
01124 if (tick_along_z)
01125 render_tickmarks (yticks, y_min, y_max, xpTick, xpTick,
01126 zpTick, zpTickN, 0., 0.,
01127 signum(zpTick-zpTickN)*fz*yticklen,
01128 1, mirror);
01129 else
01130 render_tickmarks (yticks, y_min, y_max, xpTick, xpTickN,
01131 zpTick, zpTick,
01132 signum(xPlaneN-xPlane)*fx*yticklen,
01133 0., 0., 1, mirror);
01134
01135
01136 if (yticklabels.numel () > 0)
01137 {
01138 int halign = (ystate == AXE_HORZ_DIR
01139 ? 1 : (!xyzSym || y2Dright ? 0 : 2));
01140 int valign = (ystate == AXE_VERT_DIR ? 1 : 2);
01141
01142 if (tick_along_z)
01143 render_ticktexts (yticks, yticklabels, y_min, y_max, xpTick,
01144 zpTick+signum(zpTick-zpTickN)*fz*ytickoffset,
01145 1, halign, valign, wmax, hmax);
01146 else
01147 render_ticktexts (yticks, yticklabels, y_min, y_max,
01148 xpTick+signum(xpTick-xpTickN)*fx*ytickoffset,
01149 zpTick, 1, halign, valign, wmax, hmax);
01150 }
01151
01152
01153 if (do_yminorgrid)
01154 render_grid (minorgridstyle, ymticks, y_min, y_max,
01155 xPlane, xPlaneN, layer2Dtop ? zPlaneN : zPlane,
01156 zPlaneN, 1, (zstate != AXE_DEPTH_DIR));
01157
01158
01159 if (do_yminortick)
01160 {
01161 if (tick_along_z)
01162 render_tickmarks (ymticks, y_min, y_max, xpTick, xpTick,
01163 zpTick, zpTickN, 0., 0.,
01164 signum(zpTick-zpTickN)*fz*yticklen/2,
01165 1, mirror);
01166 else
01167 render_tickmarks (ymticks, y_min, y_max, xpTick, xpTickN,
01168 zpTick, zpTick,
01169 signum(xpTick-xpTickN)*fx*yticklen/2,
01170 0., 0., 1, mirror);
01171 }
01172
01173 gh_manager::get_object (props.get_ylabel ()).set ("visible", "on");
01174 }
01175 else
01176 gh_manager::get_object (props.get_ylabel ()).set ("visible", "off");
01177 }
01178
01179 void
01180 opengl_renderer::draw_axes_z_grid (const axes::properties& props)
01181 {
01182 int zstate = props.get_zstate ();
01183 bool xySym = props.get_xySym ();
01184 bool zSign = props.get_zSign ();
01185 double zticklen = props.get_zticklen ();
01186 double ztickoffset = props.get_ztickoffset ();
01187 double fx = props.get_fx ();
01188 double fy = props.get_fy ();
01189 double xPlane = props.get_xPlane ();
01190 double xPlaneN = props.get_xPlaneN ();
01191 double yPlane = props.get_yPlane ();
01192 double yPlaneN = props.get_yPlaneN ();
01193 double z_min = props.get_z_min ();
01194 double z_max = props.get_z_max ();
01195
01196
01197
01198 if (zstate != AXE_DEPTH_DIR && props.is_visible ())
01199 {
01200 std::string gridstyle = props.get_gridlinestyle ();
01201 std::string minorgridstyle = props.get_minorgridlinestyle ();
01202 bool do_zgrid = (props.is_zgrid () && (gridstyle != "none"));
01203 bool do_zminorgrid = (props.is_zminorgrid () && (minorgridstyle != "none"));
01204 bool do_zminortick = props.is_zminortick ();
01205 Matrix zticks = xform.zscale (props.get_ztick ().matrix_value ());
01206 Matrix zmticks = xform.zscale (props.get_zmtick ().matrix_value ());
01207 string_vector zticklabels = props.get_zticklabel ().all_strings ();
01208 int wmax = 0, hmax = 0;
01209 bool mirror = props.is_box () && zstate != AXE_ANY_DIR;
01210
01211 set_color (props.get_zcolor_rgb ());
01212
01213
01214 if (do_zgrid)
01215 render_grid (gridstyle, zticks, z_min, z_max,
01216 xPlane, xPlaneN, yPlane, yPlaneN, 2, true);
01217
01218
01219 if (xySym)
01220 {
01221 if (xisinf (fy))
01222 render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,
01223 yPlane, yPlane,
01224 signum(xPlaneN-xPlane)*fx*zticklen,
01225 0., 0., 2, mirror);
01226 else
01227 render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlaneN,
01228 yPlane, yPlane, 0.,
01229 signum(yPlane-yPlaneN)*fy*zticklen,
01230 0., 2, false);
01231 }
01232 else
01233 {
01234 if (xisinf (fx))
01235 render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,
01236 yPlaneN, yPlane, 0.,
01237 signum(yPlaneN-yPlane)*fy*zticklen,
01238 0., 2, mirror);
01239 else
01240 render_tickmarks (zticks, z_min, z_max, xPlane, xPlane,
01241 yPlaneN, yPlane,
01242 signum(xPlane-xPlaneN)*fx*zticklen,
01243 0., 0., 2, false);
01244 }
01245
01246
01247 if (zticklabels.numel () > 0)
01248 {
01249 int halign = 2;
01250 int valign = (zstate == AXE_VERT_DIR ? 1 : (zSign ? 3 : 2));
01251
01252 if (xySym)
01253 {
01254 if (xisinf (fy))
01255 render_ticktexts (zticks, zticklabels, z_min, z_max,
01256 xPlaneN+signum(xPlaneN-xPlane)*fx*ztickoffset,
01257 yPlane, 2, halign, valign, wmax, hmax);
01258 else
01259 render_ticktexts (zticks, zticklabels, z_min, z_max, xPlaneN,
01260 yPlane+signum(yPlane-yPlaneN)*fy*ztickoffset,
01261 2, halign, valign, wmax, hmax);
01262 }
01263 else
01264 {
01265 if (xisinf (fx))
01266 render_ticktexts (zticks, zticklabels, z_min, z_max, xPlane,
01267 yPlaneN+signum(yPlaneN-yPlane)*fy*ztickoffset,
01268 2, halign, valign, wmax, hmax);
01269 else
01270 render_ticktexts (zticks, zticklabels, z_min, z_max,
01271 xPlane+signum(xPlane-xPlaneN)*fx*ztickoffset,
01272 yPlaneN, 2, halign, valign, wmax, hmax);
01273 }
01274 }
01275
01276
01277 if (do_zminorgrid)
01278 render_grid (minorgridstyle, zmticks, z_min, z_max,
01279 xPlane, xPlaneN, yPlane, yPlaneN, 2, true);
01280
01281
01282 if (do_zminortick)
01283 {
01284 if (xySym)
01285 {
01286 if (xisinf (fy))
01287 render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlane,
01288 yPlane, yPlane,
01289 signum(xPlaneN-xPlane)*fx*zticklen/2,
01290 0., 0., 2, mirror);
01291 else
01292 render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlaneN,
01293 yPlane, yPlane, 0.,
01294 signum(yPlane-yPlaneN)*fy*zticklen/2,
01295 0., 2, false);
01296 }
01297 else
01298 {
01299 if (xisinf (fx))
01300 render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane,
01301 yPlaneN, yPlane, 0.,
01302 signum(yPlaneN-yPlane)*fy*zticklen/2,
01303 0., 2, mirror);
01304 else
01305 render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane,
01306 yPlaneN, yPlaneN,
01307 signum(xPlane-xPlaneN)*fx*zticklen/2,
01308 0., 0., 2, false);
01309 }
01310 }
01311
01312 gh_manager::get_object (props.get_zlabel ()).set ("visible", "on");
01313 }
01314 else
01315 gh_manager::get_object (props.get_zlabel ()).set ("visible", "off");
01316 }
01317
01318 void
01319 opengl_renderer::draw_axes_children (const axes::properties& props)
01320 {
01321
01322
01323 GLboolean antialias;
01324 glGetBooleanv (GL_LINE_SMOOTH, &antialias);
01325
01326 if (antialias == GL_TRUE)
01327 glEnable (GL_LINE_SMOOTH);
01328
01329 Matrix children = props.get_all_children ();
01330 std::list<graphics_object> obj_list;
01331 std::list<graphics_object>::iterator it;
01332
01333
01334
01335
01336
01337
01338 for (octave_idx_type i = children.numel () - 1; i >= 0; i--)
01339 {
01340 graphics_object go = gh_manager::get_object (children (i));
01341
01342 if (go.get_properties ().is_visible ())
01343 {
01344 if (go.isa ("light"))
01345 draw (go);
01346 else
01347 obj_list.push_back (go);
01348 }
01349 }
01350
01351
01352
01353 it = obj_list.begin ();
01354 while (it != obj_list.end ())
01355 {
01356 graphics_object go = (*it);
01357
01358
01359
01360 if (! go.isa ("text") || go.get ("units").string_value () == "data")
01361 {
01362 set_clipping (go.get_properties ().is_clipping ());
01363 draw (go);
01364
01365 it = obj_list.erase (it);
01366 }
01367 else
01368 it++;
01369 }
01370
01371
01372
01373 glDisable (GL_DEPTH_TEST);
01374
01375 for (it = obj_list.begin (); it != obj_list.end (); it++)
01376 {
01377 graphics_object go = (*it);
01378
01379 set_clipping (go.get_properties ().is_clipping ());
01380 draw (go);
01381 }
01382
01383 glEnable (GL_DEPTH_TEST);
01384
01385 set_clipping (false);
01386
01387
01388
01389 }
01390
01391 void
01392 opengl_renderer::draw_axes (const axes::properties& props)
01393 {
01394 double x_min = props.get_x_min ();
01395 double x_max = props.get_x_max ();
01396 double y_min = props.get_y_min ();
01397 double y_max = props.get_y_max ();
01398 double z_min = props.get_z_min ();
01399 double z_max = props.get_z_max ();
01400
01401 setup_opengl_transformation (props);
01402
01403
01404
01405 draw_axes_planes (props);
01406 draw_axes_boxes (props);
01407
01408 set_font (props);
01409
01410 draw_axes_x_grid (props);
01411 draw_axes_y_grid (props);
01412 draw_axes_z_grid (props);
01413
01414 set_linestyle ("-");
01415
01416 set_clipbox (x_min, x_max, y_min, y_max, z_min, z_max);
01417
01418 draw_axes_children (props);
01419 }
01420
01421 void
01422 opengl_renderer::draw_line (const line::properties& props)
01423 {
01424 Matrix x = xform.xscale (props.get_xdata ().matrix_value ());
01425 Matrix y = xform.yscale (props.get_ydata ().matrix_value ());
01426 Matrix z = xform.zscale (props.get_zdata ().matrix_value ());
01427
01428 bool has_z = (z.numel () > 0);
01429 int n = static_cast<int> (::xmin (::xmin (x.numel (), y.numel ()), (has_z ? z.numel () : INT_MAX)));
01430 octave_uint8 clip_mask = (props.is_clipping () ? 0x7F : 0x40), clip_ok (0x40);
01431
01432 std::vector<octave_uint8> clip (n);
01433
01434 if (has_z)
01435 for (int i = 0; i < n; i++)
01436 clip[i] = (clip_code (x(i), y(i), z(i)) & clip_mask);
01437 else
01438 {
01439 double z_mid = (zmin+zmax)/2;
01440
01441 for (int i = 0; i < n; i++)
01442 clip[i] = (clip_code (x(i), y(i), z_mid) & clip_mask);
01443 }
01444
01445 if (! props.linestyle_is ("none"))
01446 {
01447 set_color (props.get_color_rgb ());
01448 set_linestyle (props.get_linestyle (), false);
01449 set_linewidth (props.get_linewidth ());
01450
01451 if (has_z)
01452 {
01453 bool flag = false;
01454
01455 for (int i = 1; i < n; i++)
01456 {
01457 if ((clip[i-1] & clip[i]) == clip_ok)
01458 {
01459 if (! flag)
01460 {
01461 flag = true;
01462 glBegin (GL_LINE_STRIP);
01463 glVertex3d (x(i-1), y(i-1), z(i-1));
01464 }
01465 glVertex3d (x(i), y(i), z(i));
01466 }
01467 else if (flag)
01468 {
01469 flag = false;
01470 glEnd ();
01471 }
01472 }
01473
01474 if (flag)
01475 glEnd ();
01476 }
01477 else
01478 {
01479 bool flag = false;
01480
01481 for (int i = 1; i < n; i++)
01482 {
01483 if ((clip[i-1] & clip[i]) == clip_ok)
01484 {
01485 if (! flag)
01486 {
01487 flag = true;
01488 glBegin (GL_LINE_STRIP);
01489 glVertex2d (x(i-1), y(i-1));
01490 }
01491 glVertex2d (x(i), y(i));
01492 }
01493 else if (flag)
01494 {
01495 flag = false;
01496 glEnd ();
01497 }
01498 }
01499
01500 if (flag)
01501 glEnd ();
01502 }
01503
01504 set_linewidth (0.5);
01505 set_linestyle ("-");
01506 }
01507
01508 set_clipping (false);
01509
01510 if (! props.marker_is ("none") &&
01511 ! (props.markeredgecolor_is ("none")
01512 && props.markerfacecolor_is ("none")))
01513 {
01514 Matrix lc, fc;
01515
01516 if (props.markeredgecolor_is ("auto"))
01517 lc = props.get_color_rgb ();
01518 else if (! props.markeredgecolor_is ("none"))
01519 lc = props.get_markeredgecolor_rgb ();
01520
01521 if (props.markerfacecolor_is ("auto"))
01522 fc = props.get_color_rgb ();
01523 else if (! props.markerfacecolor_is ("none"))
01524 fc = props.get_markerfacecolor_rgb ();
01525
01526 init_marker (props.get_marker (), props.get_markersize (),
01527 props.get_linewidth ());
01528
01529 for (int i = 0; i < n; i++)
01530 {
01531 if (clip[i] == clip_ok)
01532 draw_marker (x(i), y(i),
01533 has_z ? z(i) : static_cast<double> (i) / n,
01534 lc, fc);
01535 }
01536
01537 end_marker ();
01538 }
01539
01540 set_clipping (props.is_clipping ());
01541 }
01542
01543 void
01544 opengl_renderer::draw_surface (const surface::properties& props)
01545 {
01546 const Matrix x = xform.xscale (props.get_xdata ().matrix_value ());
01547 const Matrix y = xform.yscale (props.get_ydata ().matrix_value ());
01548 const Matrix z = xform.zscale (props.get_zdata ().matrix_value ());
01549
01550 int zr = z.rows (), zc = z.columns ();
01551
01552 NDArray c;
01553 const NDArray n = props.get_vertexnormals ().array_value ();
01554
01555
01556 Matrix a;
01557
01558 if (props.facelighting_is ("phong") || props.edgelighting_is ("phong"))
01559 warning ("opengl_renderer::draw: phong light model not supported");
01560
01561 int fc_mode = (props.facecolor_is_rgb () ? 0 :
01562 (props.facecolor_is ("flat") ? 1 :
01563 (props.facecolor_is ("interp") ? 2 :
01564 (props.facecolor_is ("texturemap") ? 3 : -1))));
01565 int fl_mode = (props.facelighting_is ("none") ? 0 :
01566 (props.facelighting_is ("flat") ? 1 : 2));
01567 int fa_mode = (props.facealpha_is_double () ? 0 :
01568 (props.facealpha_is ("flat") ? 1 : 2));
01569 int ec_mode = (props.edgecolor_is_rgb () ? 0 :
01570 (props.edgecolor_is ("flat") ? 1 :
01571 (props.edgecolor_is ("interp") ? 2 : -1)));
01572 int el_mode = (props.edgelighting_is ("none") ? 0 :
01573 (props.edgelighting_is ("flat") ? 1 : 2));
01574 int ea_mode = (props.edgealpha_is_double () ? 0 :
01575 (props.edgealpha_is ("flat") ? 1 : 2));
01576
01577 Matrix fcolor = (fc_mode == 3 ? Matrix (1, 3, 1.0) : props.get_facecolor_rgb ());
01578 Matrix ecolor = props.get_edgecolor_rgb ();
01579
01580 float as = props.get_ambientstrength ();
01581 float ds = props.get_diffusestrength ();
01582 float ss = props.get_specularstrength ();
01583 float se = props.get_specularexponent ();
01584 float cb[4] = { 0.0, 0.0, 0.0, 1.0 };
01585 double d = 1.0;
01586
01587 opengl_texture tex;
01588
01589 int i1, i2, j1, j2;
01590 bool x_mat = (x.rows () == z.rows ());
01591 bool y_mat = (y.columns () == z.columns ());
01592
01593 i1 = i2 = j1 = j2 = 0;
01594
01595 boolMatrix clip (z.dims (), false);
01596
01597 for (int i = 0; i < zr; i++)
01598 {
01599 if (x_mat)
01600 i1 = i;
01601
01602 for (int j = 0; j < zc; j++)
01603 {
01604 if (y_mat)
01605 j1 = j;
01606
01607 clip(i,j) = is_nan_or_inf (x(i1,j), y(i,j1), z(i,j));
01608 }
01609 }
01610
01611 if ((fc_mode > 0 && fc_mode < 3) || ec_mode > 0)
01612 c = props.get_color_data ().array_value ();
01613
01614 if (fa_mode > 0 || ea_mode > 0)
01615 {
01616
01617
01618 }
01619
01620 if (fl_mode > 0 || el_mode > 0)
01621 {
01622 float buf[4] = { ss, ss, ss, 1 };
01623
01624 glMaterialfv (LIGHT_MODE, GL_SPECULAR, buf);
01625 glMaterialf (LIGHT_MODE, GL_SHININESS, se);
01626 }
01627
01628
01629
01630 if (fc_mode == 3)
01631 tex = opengl_texture::create (props.get_color_data ());
01632
01633 if (! props.facecolor_is ("none"))
01634 {
01635 if (props.get_facealpha_double () == 1)
01636 {
01637 if (fc_mode == 0 || fc_mode == 3)
01638 {
01639 glColor3dv (fcolor.data ());
01640 if (fl_mode > 0)
01641 {
01642 for (int i = 0; i < 3; i++)
01643 cb[i] = as * fcolor(i);
01644 glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
01645
01646 for (int i = 0; i < 3; i++)
01647 cb[i] = ds * fcolor(i);
01648 glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
01649 }
01650 }
01651
01652 if (fl_mode > 0)
01653 glEnable (GL_LIGHTING);
01654 glShadeModel ((fc_mode == 2 || fl_mode == 2) ? GL_SMOOTH : GL_FLAT);
01655 set_polygon_offset (true, 1);
01656 if (fc_mode == 3)
01657 glEnable (GL_TEXTURE_2D);
01658
01659 for (int i = 1; i < zc; i++)
01660 {
01661 if (y_mat)
01662 {
01663 i1 = i-1;
01664 i2 = i;
01665 }
01666
01667 for (int j = 1; j < zr; j++)
01668 {
01669 if (clip(j-1, i-1) || clip (j, i-1)
01670 || clip (j-1, i) || clip (j, i))
01671 continue;
01672
01673 if (x_mat)
01674 {
01675 j1 = j-1;
01676 j2 = j;
01677 }
01678
01679 glBegin (GL_QUADS);
01680
01681
01682 if (fc_mode == 3)
01683 tex.tex_coord (double (i-1) / (zc-1), double (j-1) / (zr-1));
01684 else if (fc_mode > 0)
01685 {
01686
01687 for (int k = 0; k < 3; k++)
01688 cb[k] = c(j-1, i-1, k);
01689 glColor3fv (cb);
01690
01691 if (fl_mode > 0)
01692 {
01693 for (int k = 0; k < 3; k++)
01694 cb[k] *= as;
01695 glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
01696
01697 for (int k = 0; k < 3; k++)
01698 cb[k] = ds * c(j-1, i-1, k);
01699 glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
01700 }
01701 }
01702 if (fl_mode > 0)
01703 {
01704 d = sqrt (n(j-1,i-1,0) * n(j-1,i-1,0)
01705 + n(j-1,i-1,1) * n(j-1,i-1,1)
01706 + n(j-1,i-1,2) * n(j-1,i-1,2));
01707 glNormal3d (n(j-1,i-1,0)/d, n(j-1,i-1,1)/d, n(j-1,i-1,2)/d);
01708 }
01709 glVertex3d (x(j1,i-1), y(j-1,i1), z(j-1,i-1));
01710
01711
01712 if (fc_mode == 3)
01713 tex.tex_coord (double (i) / (zc-1), double (j-1) / (zr-1));
01714 else if (fc_mode == 2)
01715 {
01716 for (int k = 0; k < 3; k++)
01717 cb[k] = c(j-1, i, k);
01718 glColor3fv (cb);
01719
01720 if (fl_mode > 0)
01721 {
01722 for (int k = 0; k < 3; k++)
01723 cb[k] *= as;
01724 glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
01725
01726 for (int k = 0; k < 3; k++)
01727 cb[k] = ds * c(j-1, i, k);
01728 glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
01729 }
01730 }
01731
01732 if (fl_mode == 2)
01733 {
01734 d = sqrt (n(j-1,i,0) * n(j-1,i,0)
01735 + n(j-1,i,1) * n(j-1,i,1)
01736 + n(j-1,i,2) * n(j-1,i,2));
01737 glNormal3d (n(j-1,i,0)/d, n(j-1,i,1)/d, n(j-1,i,2)/d);
01738 }
01739
01740 glVertex3d (x(j1,i), y(j-1,i2), z(j-1,i));
01741
01742
01743 if (fc_mode == 3)
01744 tex.tex_coord (double (i) / (zc-1), double (j) / (zr-1));
01745 else if (fc_mode == 2)
01746 {
01747 for (int k = 0; k < 3; k++)
01748 cb[k] = c(j, i, k);
01749 glColor3fv (cb);
01750
01751 if (fl_mode > 0)
01752 {
01753 for (int k = 0; k < 3; k++)
01754 cb[k] *= as;
01755 glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
01756
01757 for (int k = 0; k < 3; k++)
01758 cb[k] = ds * c(j, i, k);
01759 glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
01760 }
01761 }
01762 if (fl_mode == 2)
01763 {
01764 d = sqrt (n(j,i,0) * n(j,i,0)
01765 + n(j,i,1) * n(j,i,1)
01766 + n(j,i,2) * n(j,i,2));
01767 glNormal3d (n(j,i,0)/d, n(j,i,1)/d, n(j,i,2)/d);
01768 }
01769 glVertex3d (x(j2,i), y(j,i2), z(j,i));
01770
01771
01772 if (fc_mode == 3)
01773 tex.tex_coord (double (i-1) / (zc-1), double (j) / (zr-1));
01774 else if (fc_mode == 2)
01775 {
01776 for (int k = 0; k < 3; k++)
01777 cb[k] = c(j, i-1, k);
01778 glColor3fv (cb);
01779
01780 if (fl_mode > 0)
01781 {
01782 for (int k = 0; k < 3; k++)
01783 cb[k] *= as;
01784 glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
01785
01786 for (int k = 0; k < 3; k++)
01787 cb[k] = ds * c(j, i-1, k);
01788 glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
01789 }
01790 }
01791 if (fl_mode == 2)
01792 {
01793 d = sqrt (n(j,i-1,0) * n(j,i-1,0)
01794 + n(j,i-1,1) * n(j,i-1,1)
01795 + n(j,i-1,2) * n(j,i-1,2));
01796 glNormal3d (n(j,i-1,0)/d, n(j,i-1,1)/d, n(j,i-1,2)/d);
01797 }
01798 glVertex3d (x(j2,i-1), y(j,i1), z(j,i-1));
01799
01800 glEnd ();
01801 }
01802 }
01803
01804 set_polygon_offset (false);
01805 if (fc_mode == 3)
01806 glDisable (GL_TEXTURE_2D);
01807
01808 if (fl_mode > 0)
01809 glDisable (GL_LIGHTING);
01810 }
01811 else
01812 {
01813
01814 }
01815 }
01816
01817 if (! props.edgecolor_is ("none"))
01818 {
01819 if (props.get_edgealpha_double () == 1)
01820 {
01821 if (ec_mode == 0)
01822 {
01823 glColor3dv (ecolor.data ());
01824 if (fl_mode > 0)
01825 {
01826 for (int i = 0; i < 3; i++)
01827 cb[i] = as * ecolor(i);
01828 glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
01829
01830 for (int i = 0; i < 3; i++)
01831 cb[i] = ds * ecolor(i);
01832 glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
01833 }
01834 }
01835
01836 if (el_mode > 0)
01837 glEnable (GL_LIGHTING);
01838 glShadeModel ((ec_mode == 2 || el_mode == 2) ? GL_SMOOTH : GL_FLAT);
01839
01840 set_linestyle (props.get_linestyle (), false);
01841 set_linewidth (props.get_linewidth ());
01842
01843
01844
01845 if (props.meshstyle_is ("both") || props.meshstyle_is ("column"))
01846 {
01847 for (int i = 0; i < zc; i++)
01848 {
01849 if (y_mat)
01850 {
01851 i1 = i-1;
01852 i2 = i;
01853 }
01854
01855 for (int j = 1; j < zr; j++)
01856 {
01857 if (clip(j-1,i) || clip(j,i))
01858 continue;
01859
01860 if (x_mat)
01861 {
01862 j1 = j-1;
01863 j2 = j;
01864 }
01865
01866 glBegin (GL_LINES);
01867
01868
01869 if (ec_mode > 0)
01870 {
01871 for (int k = 0; k < 3; k++)
01872 cb[k] = c(j-1, i, k);
01873 glColor3fv (cb);
01874
01875 if (fl_mode > 0)
01876 {
01877 for (int k = 0; k < 3; k++)
01878 cb[k] *= as;
01879 glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
01880
01881 for (int k = 0; k < 3; k++)
01882 cb[k] = ds * c(j-1, i, k);
01883 glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
01884 }
01885 }
01886 if (el_mode > 0)
01887 {
01888 d = sqrt (n(j-1,i,0) * n(j-1,i,0)
01889 + n(j-1,i,1) * n(j-1,i,1)
01890 + n(j-1,i,2) * n(j-1,i,2));
01891 glNormal3d (n(j-1,i,0)/d, n(j-1,i,1)/d, n(j-1,i,2)/d);
01892 }
01893 glVertex3d (x(j1,i), y(j-1,i2), z(j-1,i));
01894
01895
01896 if (ec_mode == 2)
01897 {
01898 for (int k = 0; k < 3; k++)
01899 cb[k] = c(j, i, k);
01900 glColor3fv (cb);
01901
01902 if (fl_mode > 0)
01903 {
01904 for (int k = 0; k < 3; k++)
01905 cb[k] *= as;
01906 glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
01907
01908 for (int k = 0; k < 3; k++)
01909 cb[k] = ds * c(j, i, k);
01910 glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
01911 }
01912 }
01913 if (el_mode == 2)
01914 {
01915 d = sqrt (n(j,i,0) * n(j,i,0)
01916 + n(j,i,1) * n(j,i,1)
01917 + n(j,i,2) * n(j,i,2));
01918 glNormal3d (n(j,i,0)/d, n(j,i,1)/d, n(j,i,2)/d);
01919 }
01920 glVertex3d (x(j2,i), y(j,i2), z(j,i));
01921
01922 glEnd ();
01923 }
01924 }
01925 }
01926
01927
01928
01929 if (props.meshstyle_is ("both") || props.meshstyle_is ("row"))
01930 {
01931 for (int j = 0; j < zr; j++)
01932 {
01933 if (x_mat)
01934 {
01935 j1 = j-1;
01936 j2 = j;
01937 }
01938
01939 for (int i = 1; i < zc; i++)
01940 {
01941 if (clip(j,i-1) || clip(j,i))
01942 continue;
01943
01944 if (y_mat)
01945 {
01946 i1 = i-1;
01947 i2 = i;
01948 }
01949
01950 glBegin (GL_LINES);
01951
01952
01953 if (ec_mode > 0)
01954 {
01955 for (int k = 0; k < 3; k++)
01956 cb[k] = c(j, i-1, k);
01957 glColor3fv (cb);
01958
01959 if (fl_mode > 0)
01960 {
01961 for (int k = 0; k < 3; k++)
01962 cb[k] *= as;
01963 glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
01964
01965 for (int k = 0; k < 3; k++)
01966 cb[k] = ds * c(j, i-1, k);
01967 glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
01968 }
01969 }
01970 if (el_mode > 0)
01971 {
01972 d = sqrt (n(j,i-1,0) * n(j,i-1,0)
01973 + n(j,i-1,1) * n(j,i-1,1)
01974 + n(j,i-1,2) * n(j,i-1,2));
01975 glNormal3d (n(j,i-1,0)/d, n(j,i-1,1)/d, n(j,i-1,2)/d);
01976 }
01977 glVertex3d (x(j2,i-1), y(j,i1), z(j,i-1));
01978
01979
01980 if (ec_mode == 2)
01981 {
01982 for (int k = 0; k < 3; k++)
01983 cb[k] = c(j, i, k);
01984 glColor3fv (cb);
01985
01986 if (fl_mode > 0)
01987 {
01988 for (int k = 0; k < 3; k++)
01989 cb[k] *= as;
01990 glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
01991
01992 for (int k = 0; k < 3; k++)
01993 cb[k] = ds * c(j, i, k);
01994 glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
01995 }
01996 }
01997 if (el_mode == 2)
01998 {
01999 d = sqrt (n(j,i,0) * n(j,i,0)
02000 + n(j,i,1) * n(j,i,1)
02001 + n(j,i,2) * n(j,i,2));
02002 glNormal3d (n(j,i,0)/d, n(j,i,1)/d, n(j,i,2)/d);
02003 }
02004 glVertex3d (x(j2,i), y(j,i2), z(j,i));
02005
02006 glEnd ();
02007 }
02008 }
02009 }
02010
02011 set_linestyle ("-");
02012 set_linewidth (0.5);
02013
02014 if (el_mode > 0)
02015 glDisable (GL_LIGHTING);
02016 }
02017 else
02018 {
02019
02020 }
02021 }
02022
02023 if (! props.marker_is ("none") &&
02024 ! (props.markeredgecolor_is ("none")
02025 && props.markerfacecolor_is ("none")))
02026 {
02027
02028
02029
02030
02031 bool do_edge = ! props.markeredgecolor_is ("none");
02032 bool do_face = ! props.markerfacecolor_is ("none");
02033
02034 Matrix mecolor = props.get_markeredgecolor_rgb ();
02035 Matrix mfcolor = props.get_markerfacecolor_rgb ();
02036 Matrix cc (1, 3, 0.0);
02037
02038 if (mecolor.numel () == 0 && props.markeredgecolor_is ("auto"))
02039 {
02040 mecolor = props.get_edgecolor_rgb ();
02041 do_edge = ! props.edgecolor_is ("none");
02042 }
02043
02044 if (mfcolor.numel () == 0 && props.markerfacecolor_is ("auto"))
02045 {
02046 mfcolor = props.get_facecolor_rgb ();
02047 do_face = ! props.facecolor_is ("none");
02048 }
02049
02050 if ((mecolor.numel () == 0 || mfcolor.numel () == 0)
02051 && c.numel () == 0)
02052 c = props.get_color_data ().array_value ();
02053
02054 init_marker (props.get_marker (), props.get_markersize (),
02055 props.get_linewidth ());
02056
02057 for (int i = 0; i < zc; i++)
02058 {
02059 if (y_mat)
02060 i1 = i;
02061
02062 for (int j = 0; j < zr; j++)
02063 {
02064 if (clip(j,i))
02065 continue;
02066
02067 if (x_mat)
02068 j1 = j;
02069
02070 if ((do_edge && mecolor.numel () == 0)
02071 || (do_face && mfcolor.numel () == 0))
02072 {
02073 for (int k = 0; k < 3; k++)
02074 cc(k) = c(j,i,k);
02075 }
02076
02077 Matrix lc = (do_edge ? (mecolor.numel () == 0 ? cc : mecolor) : Matrix ());
02078 Matrix fc = (do_face ? (mfcolor.numel () == 0 ? cc : mfcolor) : Matrix ());
02079
02080 draw_marker (x(j1,i), y(j,i1), z(j,i), lc, fc);
02081 }
02082 }
02083
02084 end_marker ();
02085 }
02086 }
02087
02088
02089
02090 void
02091 opengl_renderer::draw_patch (const patch::properties &props)
02092 {
02093 const Matrix f = props.get_faces ().matrix_value ();
02094 const Matrix v = xform.scale (props.get_vertices ().matrix_value ());
02095 Matrix c;
02096 const Matrix n = props.get_vertexnormals ().matrix_value ();
02097 Matrix a;
02098
02099 int nv = v.rows ();
02100
02101 int nf = f.rows ();
02102 int fcmax = f.columns ();
02103
02104 bool has_z = (v.columns () > 2);
02105 bool has_facecolor = false;
02106 bool has_facealpha = false;
02107
02108 int fc_mode = ((props.facecolor_is("none")
02109 || props.facecolor_is_rgb ()) ? 0 :
02110 (props.facecolor_is("flat") ? 1 : 2));
02111 int fl_mode = (props.facelighting_is ("none") ? 0 :
02112 (props.facelighting_is ("flat") ? 1 : 2));
02113 int fa_mode = (props.facealpha_is_double () ? 0 :
02114 (props.facealpha_is ("flat") ? 1 : 2));
02115 int ec_mode = ((props.edgecolor_is("none")
02116 || props.edgecolor_is_rgb ()) ? 0 :
02117 (props.edgecolor_is("flat") ? 1 : 2));
02118 int el_mode = (props.edgelighting_is ("none") ? 0 :
02119 (props.edgelighting_is ("flat") ? 1 : 2));
02120 int ea_mode = (props.edgealpha_is_double () ? 0 :
02121 (props.edgealpha_is ("flat") ? 1 : 2));
02122
02123 Matrix fcolor = props.get_facecolor_rgb ();
02124 Matrix ecolor = props.get_edgecolor_rgb ();
02125
02126 float as = props.get_ambientstrength ();
02127 float ds = props.get_diffusestrength ();
02128 float ss = props.get_specularstrength ();
02129 float se = props.get_specularexponent ();
02130
02131 boolMatrix clip (1, nv, false);
02132
02133 if (has_z)
02134 for (int i = 0; i < nv; i++)
02135 clip(i) = is_nan_or_inf (v(i,0), v(i,1), v(i,2));
02136 else
02137 for (int i = 0; i < nv; i++)
02138 clip(i) = is_nan_or_inf (v(i,0), v(i,1), 0);
02139
02140 boolMatrix clip_f (1, nf, false);
02141 Array<int> count_f (dim_vector (nf, 1), 0);
02142
02143 for (int i = 0; i < nf; i++)
02144 {
02145 bool fclip = false;
02146 int count = 0;
02147
02148 for (int j = 0; j < fcmax && ! xisnan (f(i,j)); j++, count++)
02149 fclip = (fclip || clip(int (f(i,j) - 1)));
02150
02151 clip_f(i) = fclip;
02152 count_f(i) = count;
02153 }
02154
02155 if (fc_mode > 0 || ec_mode > 0)
02156 {
02157 c = props.get_color_data ().matrix_value ();
02158
02159 if (c.rows () == 1)
02160 {
02161
02162
02163 if (fc_mode > 0)
02164 {
02165 fcolor = c;
02166 fc_mode = 0;
02167 }
02168
02169 if (ec_mode > 0)
02170 {
02171 ecolor = c;
02172 ec_mode = 0;
02173 }
02174
02175 c = Matrix ();
02176 }
02177 else
02178 has_facecolor = ((c.numel () > 0) && (c.rows () == f.rows ()));
02179 }
02180
02181 if (fa_mode > 0 || ea_mode > 0)
02182 {
02183
02184
02185 has_facealpha = ((a.numel () > 0) && (a.rows () == f.rows ()));
02186 }
02187
02188 octave_idx_type fr = f.rows ();
02189 std::vector<vertex_data> vdata (f.numel ());
02190
02191 for (int i = 0; i < nf; i++)
02192 for (int j = 0; j < count_f(i); j++)
02193 {
02194 int idx = int (f(i,j) - 1);
02195
02196 Matrix vv (1, 3, 0.0);
02197 Matrix cc;
02198 Matrix nn(1, 3, 0.0);
02199 double aa = 1.0;
02200
02201 vv(0) = v(idx,0); vv(1) = v(idx,1);
02202 if (has_z)
02203 vv(2) = v(idx,2);
02204
02205
02206 if (c.numel () > 0)
02207 {
02208 cc.resize (1, 3);
02209 if (has_facecolor)
02210 cc(0) = c(i,0), cc(1) = c(i,1), cc(2) = c(i,2);
02211 else
02212 cc(0) = c(idx,0), cc(1) = c(idx,1), cc(2) = c(idx,2);
02213 }
02214 if (a.numel () > 0)
02215 {
02216 if (has_facealpha)
02217 aa = a(i);
02218 else
02219 aa = a(idx);
02220 }
02221
02222 vdata[i+j*fr] =
02223 vertex_data (vv, cc, nn, aa, as, ds, ss, se);
02224 }
02225
02226 if (fl_mode > 0 || el_mode > 0)
02227 {
02228 float buf[4] = { ss, ss, ss, 1 };
02229
02230 glMaterialfv (LIGHT_MODE, GL_SPECULAR, buf);
02231 glMaterialf (LIGHT_MODE, GL_SHININESS, se);
02232 }
02233
02234 if (! props.facecolor_is ("none"))
02235 {
02236
02237 if (props.get_facealpha_double () == 1)
02238 {
02239 if (fc_mode == 0)
02240 {
02241 glColor3dv (fcolor.data ());
02242 if (fl_mode > 0)
02243 {
02244 float cb[4] = { 0, 0, 0, 1 };
02245
02246 for (int i = 0; i < 3; i++)
02247 cb[i] = (as * fcolor(i));
02248 glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
02249
02250 for (int i = 0; i < 3; i++)
02251 cb[i] = ds * fcolor(i);
02252 glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
02253 }
02254 }
02255
02256 if (fl_mode > 0)
02257 glEnable (GL_LIGHTING);
02258
02259
02260 patch_tesselator tess (this, fc_mode, fl_mode, 0);
02261
02262 for (int i = 0; i < nf; i++)
02263 {
02264 if (clip_f(i))
02265 continue;
02266
02267 tess.begin_polygon (true);
02268 tess.begin_contour ();
02269
02270 for (int j = 0; j < count_f(i); j++)
02271 {
02272 vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep ();
02273
02274 tess.add_vertex (vv->coords.fortran_vec (), vv);
02275 }
02276
02277 tess.end_contour ();
02278 tess.end_polygon ();
02279 }
02280
02281 if (fl_mode > 0)
02282 glDisable (GL_LIGHTING);
02283 }
02284 else
02285 {
02286
02287 }
02288 }
02289
02290 if (! props.edgecolor_is ("none"))
02291 {
02292
02293 if (props.get_edgealpha_double () == 1)
02294 {
02295 if (ec_mode == 0)
02296 {
02297 glColor3dv (ecolor.data ());
02298 if (el_mode > 0)
02299 {
02300 float cb[4] = { 0, 0, 0, 1 };
02301
02302 for (int i = 0; i < 3; i++)
02303 cb[i] = (as * ecolor(i));
02304 glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
02305
02306 for (int i = 0; i < 3; i++)
02307 cb[i] = ds * ecolor(i);
02308 glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
02309 }
02310 }
02311
02312 if (el_mode > 0)
02313 glEnable (GL_LIGHTING);
02314
02315 set_linestyle (props.get_linestyle (), false);
02316 set_linewidth (props.get_linewidth ());
02317
02318
02319
02320
02321 patch_tesselator tess (this, ec_mode, el_mode);
02322
02323 for (int i = 0; i < nf; i++)
02324 {
02325 if (clip_f(i))
02326 {
02327
02328 bool flag = false;
02329
02330 for (int j = 0; j < count_f(i); j++)
02331 {
02332 if (! clip(int (f(i,j) - 1)))
02333 {
02334 vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep ();
02335 const Matrix m = vv->coords;
02336 if (! flag)
02337 {
02338 flag = true;
02339 glBegin (GL_LINE_STRIP);
02340 }
02341 glVertex3d (m(0), m(1), m(2));
02342 }
02343 else if (flag)
02344 {
02345 flag = false;
02346 glEnd ();
02347 }
02348 }
02349
02350 if (flag)
02351 glEnd ();
02352 }
02353 else
02354 {
02355 tess.begin_polygon (false);
02356 tess.begin_contour ();
02357
02358 for (int j = 0; j < count_f(i); j++)
02359 {
02360 vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep ();
02361 tess.add_vertex (vv->coords.fortran_vec (), vv);
02362 }
02363
02364 tess.end_contour ();
02365 tess.end_polygon ();
02366 }
02367 }
02368
02369 set_linestyle ("-");
02370 set_linewidth (0.5);
02371
02372 if (el_mode > 0)
02373 glDisable (GL_LIGHTING);
02374 }
02375 else
02376 {
02377
02378 }
02379 }
02380
02381 if (! props.marker_is ("none") &&
02382 ! (props.markeredgecolor_is ("none") && props.markerfacecolor_is ("none")))
02383 {
02384 bool do_edge = ! props.markeredgecolor_is ("none");
02385 bool do_face = ! props.markerfacecolor_is ("none");
02386
02387 Matrix mecolor = props.get_markeredgecolor_rgb ();
02388 Matrix mfcolor = props.get_markerfacecolor_rgb ();
02389
02390 bool has_markerfacecolor = false;
02391
02392 if ((mecolor.numel () == 0 && ! props.markeredgecolor_is ("none"))
02393 || (mfcolor.numel () == 0 && ! props.markerfacecolor_is ("none")))
02394 {
02395 Matrix mc = props.get_color_data ().matrix_value ();
02396
02397 if (mc.rows () == 1)
02398 {
02399
02400
02401 if (mfcolor.numel () == 0
02402 && ! props.markerfacecolor_is ("none"))
02403 mfcolor = mc;
02404
02405 if (mecolor.numel () == 0
02406 && ! props.markeredgecolor_is ("none"))
02407 mecolor = mc;
02408 }
02409 else
02410 {
02411 if (c.numel () == 0)
02412 c = props.get_color_data ().matrix_value ();
02413 has_markerfacecolor = ((c.numel () > 0)
02414 && (c.rows () == f.rows ()));
02415 }
02416 }
02417
02418
02419 init_marker (props.get_marker (), props.get_markersize (),
02420 props.get_linewidth ());
02421
02422 for (int i = 0; i < nf; i++)
02423 for (int j = 0; j < count_f(i); j++)
02424 {
02425 int idx = int (f(i,j) - 1);
02426
02427 if (clip(idx))
02428 continue;
02429
02430 Matrix cc;
02431 if (c.numel () > 0)
02432 {
02433 cc.resize (1, 3);
02434 if (has_markerfacecolor)
02435 cc(0) = c(i,0), cc(1) = c(i,1), cc(2) = c(i,2);
02436 else
02437 cc(0) = c(idx,0), cc(1) = c(idx,1), cc(2) = c(idx,2);
02438 }
02439
02440 Matrix lc = (do_edge ? (mecolor.numel () == 0 ? cc : mecolor)
02441 : Matrix ());
02442 Matrix fc = (do_face ? (mfcolor.numel () == 0 ? cc : mfcolor)
02443 : Matrix ());
02444
02445 draw_marker (v(idx,0), v(idx,1), (has_z ? v(idx,2) : 0), lc, fc);
02446 }
02447
02448 end_marker ();
02449 }
02450 }
02451
02452 void
02453 opengl_renderer::draw_hggroup (const hggroup::properties &props)
02454 {
02455 draw (props.get_children ());
02456 }
02457
02458 void
02459 opengl_renderer::draw_text (const text::properties& props)
02460 {
02461 if (props.get_string ().is_empty ())
02462 return;
02463
02464 Matrix pos = xform.scale (props.get_data_position ());
02465 const Matrix bbox = props.get_extent_matrix ();
02466
02467
02468 bool blend = glIsEnabled (GL_BLEND);
02469
02470 glEnable (GL_BLEND);
02471 glEnable (GL_ALPHA_TEST);
02472 glRasterPos3d (pos(0), pos(1), pos.numel () > 2 ? pos(2) : 0.0);
02473 glBitmap(0, 0, 0, 0, bbox(0), bbox(1), 0);
02474 glDrawPixels (bbox(2), bbox(3),
02475 GL_RGBA, GL_UNSIGNED_BYTE, props.get_pixels ().data ());
02476 glDisable (GL_ALPHA_TEST);
02477 if (! blend)
02478 glDisable (GL_BLEND);
02479
02480 }
02481
02482 void
02483 opengl_renderer::draw_image (const image::properties& props)
02484 {
02485 octave_value cdata = props.get_color_data ();
02486 dim_vector dv (cdata.dims ());
02487 int h = dv(0), w = dv(1);
02488
02489 Matrix x = props.get_xdata ().matrix_value ();
02490 Matrix y = props.get_ydata ().matrix_value ();
02491
02492 if (w > 1 && x(1) == x(0))
02493 x(1) = x(1) + (w-1);
02494
02495 if (h > 1 && y(1) == y(0))
02496 y(1) = y(1) + (h-1);
02497
02498 const ColumnVector p0 = xform.transform (x(0), y(0), 0);
02499 const ColumnVector p1 = xform.transform (x(1), y(1), 0);
02500
02501
02502 float pix_dx, pix_dy;
02503
02504 float nor_dx, nor_dy;
02505
02506 if (w > 1)
02507 {
02508 pix_dx = (p1(0) - p0(0))/(w-1);
02509 nor_dx = (x(1) - x(0))/(w-1);
02510 }
02511 else
02512 {
02513 const ColumnVector p1w = xform.transform (x(1) + 1, y(1), 0);
02514 pix_dx = p1w(0) - p0(0);
02515 nor_dx = 1;
02516 }
02517
02518 if (h > 1)
02519 {
02520 pix_dy = (p1(1) - p0(1))/(h-1);
02521 nor_dy = (y(1) - y(0))/(h-1);
02522 }
02523 else
02524 {
02525 const ColumnVector p1h = xform.transform (x(1), y(1) + 1, 0);
02526 pix_dy = p1h(1) - p0(1);
02527 nor_dy = 1;
02528 }
02529
02530
02531
02532
02533
02534
02535 int j0 = 0, j1 = w;
02536 int i0 = 0, i1 = h;
02537
02538 float im_xmin = x(0) - nor_dx/2;
02539 float im_xmax = x(1) + nor_dx/2;
02540 float im_ymin = y(0) - nor_dy/2;
02541 float im_ymax = y(1) + nor_dy/2;
02542 if (props.is_clipping ())
02543 {
02544 if (im_xmin < xmin)
02545 j0 += (xmin - im_xmin)/nor_dx + 1;
02546 if (im_xmax > xmax)
02547 j1 -= (im_xmax - xmax)/nor_dx ;
02548
02549 if (im_ymin < ymin)
02550 i0 += (ymin - im_ymin)/nor_dy + 1;
02551 if (im_ymax > ymax)
02552 i1 -= (im_ymax - ymax)/nor_dy;
02553 }
02554 else
02555 {
02556 GLfloat vp[4];
02557 glGetFloatv(GL_VIEWPORT, vp);
02558
02559
02560 }
02561
02562 if (i0 >= i1 || j0 >= j1)
02563 return;
02564
02565 glPixelZoom (pix_dx, -pix_dy);
02566 glRasterPos3d (im_xmin + nor_dx*j0, im_ymin + nor_dy*i0, 0);
02567
02568
02569 glPixelStorei (GL_UNPACK_ALIGNMENT,1);
02570
02571
02572 if (dv.length () == 3 && dv(2) == 3)
02573 {
02574 if (cdata.is_double_type ())
02575 {
02576 const NDArray xcdata = cdata.array_value ();
02577
02578 OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0));
02579
02580 for (int i = i0; i < i1; i++)
02581 {
02582 for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
02583 {
02584 a[idx] = xcdata(i,j,0);
02585 a[idx+1] = xcdata(i,j,1);
02586 a[idx+2] = xcdata(i,j,2);
02587 }
02588 }
02589
02590 draw_pixels (j1-j0, i1-i0, GL_RGB, GL_FLOAT, a);
02591
02592 }
02593 else if (cdata.is_uint16_type ())
02594 {
02595 const uint16NDArray xcdata = cdata.uint16_array_value ();
02596
02597 OCTAVE_LOCAL_BUFFER (GLushort, a, 3*(j1-j0)*(i1-i0));
02598
02599 for (int i = i0; i < i1; i++)
02600 {
02601 for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
02602 {
02603 a[idx] = xcdata(i,j,0);
02604 a[idx+1] = xcdata(i,j,1);
02605 a[idx+2] = xcdata(i,j,2);
02606 }
02607 }
02608
02609 draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_SHORT, a);
02610
02611 }
02612 else if (cdata.is_uint8_type ())
02613 {
02614 const uint8NDArray xcdata = cdata.uint8_array_value ();
02615
02616 OCTAVE_LOCAL_BUFFER (GLubyte, a, 3*(j1-j0)*(i1-i0));
02617
02618 for (int i = i0; i < i1; i++)
02619 {
02620 for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
02621 {
02622 a[idx] = xcdata(i,j,0);
02623 a[idx+1] = xcdata(i,j,1);
02624 a[idx+2] = xcdata(i,j,2);
02625 }
02626 }
02627
02628 draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_BYTE, a);
02629 }
02630 else
02631 warning ("opengl_texture::draw: invalid image data type (expected double, uint16, or uint8)");
02632 }
02633 else
02634 warning ("opengl_texture::draw: invalid image size (expected n*m*3 or n*m)");
02635
02636 glPixelZoom (1, 1);
02637 }
02638
02639 void
02640 opengl_renderer::set_viewport (int w, int h)
02641 {
02642 glViewport (0, 0, w, h);
02643 }
02644
02645 void
02646 opengl_renderer::draw_pixels (GLsizei width, GLsizei height, GLenum format,
02647 GLenum type, const GLvoid *data)
02648 {
02649 glDrawPixels (width, height, format, type, data);
02650 }
02651
02652 void
02653 opengl_renderer::set_color (const Matrix& c)
02654 {
02655 glColor3dv (c.data ());
02656 #if HAVE_FREETYPE
02657 text_renderer.set_color (c);
02658 #endif
02659 }
02660
02661 void
02662 opengl_renderer::set_font (const base_properties& props)
02663 {
02664 #if HAVE_FREETYPE
02665 text_renderer.set_font (props.get ("fontname").string_value (),
02666 props.get ("fontweight").string_value (),
02667 props.get ("fontangle").string_value (),
02668 props.get ("fontsize").double_value ());
02669 #endif
02670 }
02671
02672 void
02673 opengl_renderer::set_polygon_offset (bool on, double offset)
02674 {
02675 if (on)
02676 {
02677 glPolygonOffset (offset, offset);
02678 glEnable (GL_POLYGON_OFFSET_FILL);
02679 glEnable (GL_POLYGON_OFFSET_LINE);
02680 }
02681 else
02682 {
02683 glDisable (GL_POLYGON_OFFSET_FILL);
02684 glDisable (GL_POLYGON_OFFSET_LINE);
02685 }
02686 }
02687
02688 void
02689 opengl_renderer::set_linewidth (float w)
02690 {
02691 glLineWidth (w);
02692 }
02693
02694 void
02695 opengl_renderer::set_linestyle (const std::string& s, bool use_stipple)
02696 {
02697 bool solid = false;
02698
02699 if (s == "-")
02700 {
02701 glLineStipple (1, static_cast<unsigned short> (0xFFFF));
02702 solid = true;
02703 }
02704 else if (s == ":")
02705 glLineStipple (1, static_cast<unsigned short> (0x8888));
02706 else if (s == "--")
02707 glLineStipple (1, static_cast<unsigned short> (0x0FFF));
02708 else if (s == "-.")
02709 glLineStipple (1, static_cast<unsigned short> (0x020F));
02710 else
02711 glLineStipple (1, static_cast<unsigned short> (0x0000));
02712
02713 if (solid && ! use_stipple)
02714 glDisable (GL_LINE_STIPPLE);
02715 else
02716 glEnable (GL_LINE_STIPPLE);
02717 }
02718
02719 void
02720 opengl_renderer::set_clipbox (double x1, double x2, double y1, double y2,
02721 double z1, double z2)
02722 {
02723 double dx = (x2-x1);
02724 double dy = (y2-y1);
02725 double dz = (z2-z1);
02726
02727 x1 -= 0.001*dx; x2 += 0.001*dx;
02728 y1 -= 0.001*dy; y2 += 0.001*dy;
02729 z1 -= 0.001*dz; z2 += 0.001*dz;
02730
02731 ColumnVector p (4, 0.0);
02732
02733 p(0) = -1; p(3) = x2;
02734 glClipPlane (GL_CLIP_PLANE0, p.data ());
02735 p(0) = 1; p(3) = -x1;
02736 glClipPlane (GL_CLIP_PLANE1, p.data ());
02737 p(0) = 0; p(1) = -1; p(3) = y2;
02738 glClipPlane (GL_CLIP_PLANE2, p.data ());
02739 p(1) = 1; p(3) = -y1;
02740 glClipPlane (GL_CLIP_PLANE3, p.data ());
02741 p(1) = 0; p(2) = -1; p(3) = z2;
02742 glClipPlane (GL_CLIP_PLANE4, p.data ());
02743 p(2) = 1; p(3) = -z1;
02744 glClipPlane (GL_CLIP_PLANE5, p.data ());
02745
02746 xmin = x1; xmax = x2;
02747 ymin = y1; ymax = y2;
02748 zmin = z1; zmax = z2;
02749 }
02750
02751 void
02752 opengl_renderer::set_clipping (bool enable)
02753 {
02754 bool has_clipping = (glIsEnabled (GL_CLIP_PLANE0) == GL_TRUE);
02755
02756 if (enable != has_clipping)
02757 {
02758 if (enable)
02759 for (int i = 0; i < 6; i++)
02760 glEnable (GL_CLIP_PLANE0+i);
02761 else
02762 for (int i = 0; i < 6; i++)
02763 glDisable (GL_CLIP_PLANE0+i);
02764 }
02765 }
02766
02767 void
02768 opengl_renderer::init_marker (const std::string& m, double size, float width)
02769 {
02770 #if defined (HAVE_FRAMEWORK_OPENGL)
02771 GLint vw[4];
02772 #else
02773 int vw[4];
02774 #endif
02775
02776 glGetIntegerv (GL_VIEWPORT, vw);
02777
02778 glMatrixMode (GL_PROJECTION);
02779 glPushMatrix ();
02780 glLoadIdentity ();
02781 glOrtho (0, vw[2], vw[3], 0, xZ1, xZ2);
02782 glMatrixMode (GL_MODELVIEW);
02783 glPushMatrix ();
02784
02785 set_clipping (false);
02786 set_linewidth (width);
02787
02788 marker_id = make_marker_list (m, size, false);
02789 filled_marker_id = make_marker_list (m, size, true);
02790 }
02791
02792 void
02793 opengl_renderer::end_marker (void)
02794 {
02795 glDeleteLists (marker_id, 1);
02796 glDeleteLists (filled_marker_id, 1);
02797
02798 glMatrixMode (GL_MODELVIEW);
02799 glPopMatrix ();
02800 glMatrixMode (GL_PROJECTION);
02801 glPopMatrix ();
02802 set_linewidth (0.5f);
02803 }
02804
02805 void
02806 opengl_renderer::draw_marker (double x, double y, double z,
02807 const Matrix& lc, const Matrix& fc)
02808 {
02809 ColumnVector tmp = xform.transform (x, y, z, false);
02810
02811 glLoadIdentity ();
02812 glTranslated (tmp(0), tmp(1), -tmp(2));
02813
02814 if (filled_marker_id > 0 && fc.numel () > 0)
02815 {
02816 glColor3dv (fc.data ());
02817 set_polygon_offset (true, -1.0);
02818 glCallList (filled_marker_id);
02819 if (lc.numel () > 0)
02820 {
02821 glColor3dv (lc.data ());
02822 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
02823 glEdgeFlag (GL_TRUE);
02824 set_polygon_offset (true, -2.0);
02825 glCallList (filled_marker_id);
02826 glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
02827 }
02828 set_polygon_offset (false);
02829 }
02830 else if (marker_id > 0 && lc.numel () > 0)
02831 {
02832 glColor3dv (lc.data ());
02833 glCallList (marker_id);
02834 }
02835 }
02836
02837 unsigned int
02838 opengl_renderer::make_marker_list (const std::string& marker, double size,
02839 bool filled) const
02840 {
02841 char c = marker[0];
02842
02843 if (filled && (c == '+' || c == 'x' || c == '*' || c == '.'))
02844 return 0;
02845
02846 unsigned int ID = glGenLists (1);
02847 double sz = size * toolkit.get_screen_resolution () / 72.0;
02848
02849
02850 const double sqrt2d4 = 0.35355339059327;
02851 double tt = sz*sqrt2d4;
02852
02853 glNewList (ID, GL_COMPILE);
02854
02855 switch (marker[0])
02856 {
02857 case '+':
02858 glBegin (GL_LINES);
02859 glVertex2f (-sz/2, 0);
02860 glVertex2f (sz/2, 0);
02861 glVertex2f (0, -sz/2);
02862 glVertex2f (0, sz/2);
02863 glEnd ();
02864 break;
02865 case 'x':
02866 glBegin(GL_LINES);
02867 glVertex2f (-sz/2, -sz/2);
02868 glVertex2f (sz/2, sz/2);
02869 glVertex2f (-sz/2, sz/2);
02870 glVertex2f (sz/2, -sz/2);
02871 glEnd ();
02872 break;
02873 case '*':
02874 glBegin (GL_LINES);
02875 glVertex2f (-sz/2, 0);
02876 glVertex2f (sz/2, 0);
02877 glVertex2f (0, -sz/2);
02878 glVertex2f (0, sz/2);
02879 glVertex2f (-tt, -tt);
02880 glVertex2f (+tt, +tt);
02881 glVertex2f (-tt, +tt);
02882 glVertex2f (+tt, -tt);
02883 glEnd ();
02884 break;
02885 case '.':
02886 {
02887 double ang_step = M_PI / 5;
02888
02889 glBegin (GL_POLYGON);
02890 for (double ang = 0; ang < (2*M_PI); ang += ang_step)
02891 glVertex2d (sz*cos(ang)/3, sz*sin(ang)/3);
02892 glEnd ();
02893 }
02894 break;
02895 case 's':
02896 glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
02897 glVertex2d (-sz/2, -sz/2);
02898 glVertex2d (-sz/2, sz/2);
02899 glVertex2d (sz/2, sz/2);
02900 glVertex2d (sz/2, -sz/2);
02901 glEnd();
02902 break;
02903 case 'o':
02904 {
02905 double ang_step = M_PI / 5;
02906
02907 glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
02908 for (double ang = 0; ang < (2*M_PI); ang += ang_step)
02909 glVertex2d (sz*cos(ang)/2, sz*sin(ang)/2);
02910 glEnd ();
02911 }
02912 break;
02913 case 'd':
02914 glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
02915 glVertex2d (0, -sz/2);
02916 glVertex2d (sz/2, 0);
02917 glVertex2d (0, sz/2);
02918 glVertex2d (-sz/2, 0);
02919 glEnd();
02920 break;
02921 case 'v':
02922 glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
02923 glVertex2f (0, sz/2);
02924 glVertex2f (sz/2, -sz/2);
02925 glVertex2f (-sz/2, -sz/2);
02926 glEnd ();
02927 break;
02928 case '^':
02929 glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
02930 glVertex2f (0, -sz/2);
02931 glVertex2f (-sz/2, sz/2);
02932 glVertex2f (sz/2, sz/2);
02933 glEnd ();
02934 break;
02935 case '>':
02936 glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
02937 glVertex2f (sz/2, 0);
02938 glVertex2f (-sz/2, sz/2);
02939 glVertex2f (-sz/2, -sz/2);
02940 glEnd ();
02941 break;
02942 case '<':
02943 glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
02944 glVertex2f (-sz/2, 0);
02945 glVertex2f (sz/2, -sz/2);
02946 glVertex2f (sz/2, sz/2);
02947 glEnd ();
02948 break;
02949 case 'p':
02950 {
02951 double ang;
02952 double r;
02953 double dr = 1.0 - sin(M_PI/10)/sin(3*M_PI/10)*1.02;
02954
02955 glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
02956 for (int i = 0; i < 2*5; i++)
02957 {
02958 ang = (-0.5 + double(i+1)/5) * M_PI;
02959 r = 1.0 - (dr * fmod(double(i+1), 2.0));
02960 glVertex2d (sz*r*cos(ang)/2, sz*r*sin(ang)/2);
02961 }
02962 glEnd ();
02963 }
02964 break;
02965 case 'h':
02966 {
02967 double ang;
02968 double r;
02969 double dr = 1.0 - 0.5/sin(M_PI/3)*1.02;
02970
02971 glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
02972 for (int i = 0; i < 2*6; i++)
02973 {
02974 ang = (0.5 + double(i+1)/6.0) * M_PI;
02975 r = 1.0 - (dr * fmod(double(i+1), 2.0));
02976 glVertex2d (sz*r*cos(ang)/2, sz*r*sin(ang)/2);
02977 }
02978 glEnd ();
02979 }
02980 break;
02981 default:
02982 warning ("opengl_renderer: unsupported marker '%s'",
02983 marker.c_str ());
02984 break;
02985 }
02986
02987 glEndList ();
02988
02989 return ID;
02990 }
02991
02992 void
02993 opengl_renderer::text_to_pixels (const std::string& txt,
02994 uint8NDArray& pixels,
02995 Matrix& bbox,
02996 int halign, int valign, double rotation)
02997 {
02998 #if HAVE_FREETYPE
02999 text_renderer.text_to_pixels (txt, pixels, bbox,
03000 halign, valign, rotation);
03001 #endif
03002 }
03003
03004 Matrix
03005 opengl_renderer::render_text (const std::string& txt,
03006 double x, double y, double z,
03007 int halign, int valign, double rotation)
03008 {
03009 #if HAVE_FREETYPE
03010 if (txt.empty ())
03011 return Matrix (1, 4, 0.0);
03012
03013 uint8NDArray pixels;
03014 Matrix bbox;
03015 text_to_pixels (txt, pixels, bbox, halign, valign, rotation);
03016
03017 bool blend = glIsEnabled (GL_BLEND);
03018
03019 glEnable (GL_BLEND);
03020 glEnable (GL_ALPHA_TEST);
03021 glRasterPos3d (x, y, z);
03022 glBitmap(0, 0, 0, 0, bbox(0), bbox(1), 0);
03023 glDrawPixels (bbox(2), bbox(3),
03024 GL_RGBA, GL_UNSIGNED_BYTE, pixels.data ());
03025 glDisable (GL_ALPHA_TEST);
03026 if (! blend)
03027 glDisable (GL_BLEND);
03028
03029 return bbox;
03030 #else
03031 ::warning ("render_text: cannot render text, Freetype library not available");
03032 return Matrix (1, 4, 0.0);
03033 #endif
03034 }
03035
03036 #endif