11 #include "gui-pinout-preview.h"
13 /* The Linux OpenGL ABI 1.0 spec requires that we define
14 * GL_GLEXT_PROTOTYPES before including gl.h or glx.h for extensions
15 * in order to get prototypes:
16 * http://www.opengl.org/registry/ABI/
19 #define GL_GLEXT_PROTOTYPES 1
20 #ifdef HAVE_OPENGL_GL_H
21 # include <OpenGL/gl.h>
26 #include <gtk/gtkgl.h>
27 #include "hid/common/hidgl.h"
29 #include "hid/common/draw_helpers.h"
30 #include "hid/common/trackball.h"
32 #ifdef HAVE_LIBDMALLOC
37 extern HID_DRAW ghid_graphics
;
39 static hidGC current_gc
= NULL
;
41 /* Sets gport->u_gc to the "right" GC to use (wrt mask or window)
43 #define USE_GC(gc) if (!use_gc(gc)) return
45 static enum mask_mode cur_mask
= HID_MASK_OFF
;
46 static GLfloat view_matrix
[4][4] = {{1.0, 0.0, 0.0, 0.0},
49 {0.0, 0.0, 0.0, 1.0}};
50 static GLfloat last_modelview_matrix
[4][4] = {{1.0, 0.0, 0.0, 0.0},
53 {0.0, 0.0, 0.0, 1.0}};
54 static int global_view_2d
= 1;
56 typedef struct render_priv
{
57 GdkGLConfig
*glconfig
;
60 int subcomposite_stencil_bit
;
61 char *current_colorname
;
62 double current_alpha_mult
;
63 GTimer
*time_since_expose
;
65 /* Feature for leading the user to a particular location */
66 guint lead_user_timeout
;
67 GTimer
*lead_user_timer
;
69 Coord lead_user_radius
;
77 typedef struct hid_gc_struct
81 const char *colorname
;
89 static void draw_lead_user (render_priv
*priv
);
90 static void ghid_unproject_to_z_plane (int ex
, int ey
, Coord pcb_z
, Coord
*pcb_x
, Coord
*pcb_y
);
94 start_subcomposite (void)
96 render_priv
*priv
= gport
->render_priv
;
99 /* Flush out any existing geoemtry to be rendered */
100 hidgl_flush_triangles (&buffer
);
102 glEnable (GL_STENCIL_TEST
); /* Enable Stencil test */
103 glStencilOp (GL_KEEP
, GL_KEEP
, GL_REPLACE
); /* Stencil pass => replace stencil value (with 1) */
105 stencil_bit
= hidgl_assign_clear_stencil_bit(); /* Get a new (clean) bitplane to stencil with */
106 glStencilMask (stencil_bit
); /* Only write to our subcompositing stencil bitplane */
107 glStencilFunc (GL_GREATER
, stencil_bit
, stencil_bit
); /* Pass stencil test if our assigned bit is clear */
109 priv
->subcomposite_stencil_bit
= stencil_bit
;
113 end_subcomposite (void)
115 render_priv
*priv
= gport
->render_priv
;
117 /* Flush out any existing geoemtry to be rendered */
118 hidgl_flush_triangles (&buffer
);
120 hidgl_return_stencil_bit (priv
->subcomposite_stencil_bit
); /* Relinquish any bitplane we previously used */
123 glStencilFunc (GL_ALWAYS
, 0, 0); /* Always pass stencil test */
124 glDisable (GL_STENCIL_TEST
); /* Disable Stencil test */
126 priv
->subcomposite_stencil_bit
= 0;
131 ghid_set_layer (const char *name
, int group
, int empty
)
133 render_priv
*priv
= gport
->render_priv
;
135 if (idx
>= 0 && idx
< max_group
)
137 int n
= PCB
->LayerGroups
.Number
[group
];
138 for (idx
= 0; idx
< n
-1; idx
++)
140 int ni
= PCB
->LayerGroups
.Entries
[group
][idx
];
141 if (ni
>= 0 && ni
< max_copper_layer
+ 2
142 && PCB
->Data
->Layer
[ni
].On
)
145 idx
= PCB
->LayerGroups
.Entries
[group
][idx
];
149 start_subcomposite ();
151 if (idx
>= 0 && idx
< max_copper_layer
+ 2)
153 priv
->trans_lines
= true;
154 return PCB
->Data
->Layer
[idx
].On
;
158 switch (SL_TYPE (idx
))
161 return PCB
->InvisibleObjectsOn
;
164 return TEST_FLAG (SHOWMASKFLAG
, PCB
);
167 priv
->trans_lines
= true;
169 return PCB
->ElementOn
;
178 priv
->trans_lines
= true;
186 ghid_end_layer (void)
192 ghid_destroy_gc (hidGC gc
)
202 rv
= g_new0 (hid_gc_struct
, 1);
203 rv
->me_pointer
= &ghid_hid
;
204 rv
->colorname
= Settings
.BackgroundColor
;
205 rv
->alpha_mult
= 1.0;
210 ghid_draw_grid (BoxType
*drawn_area
)
212 if (Vz (PCB
->Grid
) < MIN_GRID_DISTANCE
)
215 if (gdk_color_parse (Settings
.GridColor
, &gport
->grid_color
))
217 gport
->grid_color
.red
^= gport
->bg_color
.red
;
218 gport
->grid_color
.green
^= gport
->bg_color
.green
;
219 gport
->grid_color
.blue
^= gport
->bg_color
.blue
;
222 glEnable (GL_COLOR_LOGIC_OP
);
225 glColor3f (gport
->grid_color
.red
/ 65535.,
226 gport
->grid_color
.green
/ 65535.,
227 gport
->grid_color
.blue
/ 65535.);
229 hidgl_draw_grid (drawn_area
);
231 glDisable (GL_COLOR_LOGIC_OP
);
235 ghid_draw_bg_image (void)
237 static GLuint texture_handle
= 0;
239 if (!ghidgui
->bg_pixbuf
)
242 if (texture_handle
== 0)
244 int width
= gdk_pixbuf_get_width (ghidgui
->bg_pixbuf
);
245 int height
= gdk_pixbuf_get_height (ghidgui
->bg_pixbuf
);
246 int rowstride
= gdk_pixbuf_get_rowstride (ghidgui
->bg_pixbuf
);
247 int bits_per_sample
= gdk_pixbuf_get_bits_per_sample (ghidgui
->bg_pixbuf
);
248 int n_channels
= gdk_pixbuf_get_n_channels (ghidgui
->bg_pixbuf
);
249 unsigned char *pixels
= gdk_pixbuf_get_pixels (ghidgui
->bg_pixbuf
);
251 g_warn_if_fail (bits_per_sample
== 8);
252 g_warn_if_fail (rowstride
== width
* n_channels
);
254 glGenTextures (1, &texture_handle
);
255 glBindTexture (GL_TEXTURE_2D
, texture_handle
);
257 /* XXX: We should proabbly determine what the maxmimum texture supported is,
258 * and if our image is larger, shrink it down using GDK pixbuf routines
259 * rather than having it fail below.
262 glTexImage2D (GL_TEXTURE_2D
, 0, GL_RGB
, width
, height
, 0,
263 (n_channels
== 4) ? GL_RGBA
: GL_RGB
, GL_UNSIGNED_BYTE
, pixels
);
266 glBindTexture (GL_TEXTURE_2D
, texture_handle
);
268 glTexEnvf (GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_DECAL
);
269 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
270 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
271 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
272 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
273 glEnable (GL_TEXTURE_2D
);
275 /* Render a quad with the background as a texture */
278 glTexCoord2d (0., 0.);
279 glVertex3i (0, 0, 0);
280 glTexCoord2d (1., 0.);
281 glVertex3i (PCB
->MaxWidth
, 0, 0);
282 glTexCoord2d (1., 1.);
283 glVertex3i (PCB
->MaxWidth
, PCB
->MaxHeight
, 0);
284 glTexCoord2d (0., 1.);
285 glVertex3i (0, PCB
->MaxHeight
, 0);
288 glDisable (GL_TEXTURE_2D
);
292 ghid_use_mask (enum mask_mode mode
)
294 static int stencil_bit
= 0;
296 if (mode
== cur_mask
)
299 /* Flush out any existing geoemtry to be rendered */
300 hidgl_flush_triangles (&buffer
);
304 case HID_MASK_BEFORE
:
305 /* The HID asks not to receive this mask type, so warn if we get it */
306 g_return_if_reached ();
309 /* Write '1' to the stencil buffer where the solder-mask should not be drawn. */
310 glColorMask (0, 0, 0, 0); /* Disable writting in color buffer */
311 glEnable (GL_STENCIL_TEST
); /* Enable Stencil test */
312 stencil_bit
= hidgl_assign_clear_stencil_bit(); /* Get a new (clean) bitplane to stencil with */
313 glStencilFunc (GL_ALWAYS
, stencil_bit
, stencil_bit
); /* Always pass stencil test, write stencil_bit */
314 glStencilMask (stencil_bit
); /* Only write to our subcompositing stencil bitplane */
315 glStencilOp (GL_KEEP
, GL_KEEP
, GL_REPLACE
); /* Stencil pass => replace stencil value (with 1) */
319 /* Drawing operations as masked to areas where the stencil buffer is '0' */
320 glColorMask (1, 1, 1, 1); /* Enable drawing of r, g, b & a */
321 glStencilFunc (GL_GEQUAL
, 0, stencil_bit
); /* Draw only where our bit of the stencil buffer is clear */
322 glStencilOp (GL_KEEP
, GL_KEEP
, GL_KEEP
); /* Stencil buffer read only */
326 /* Disable stenciling */
327 hidgl_return_stencil_bit (stencil_bit
); /* Relinquish any bitplane we previously used */
328 glDisable (GL_STENCIL_TEST
); /* Disable Stencil test */
335 /* Config helper functions for when the user changes color preferences.
336 | set_special colors used in the gtkhid.
339 set_special_grid_color (void)
341 if (!gport
->colormap
)
343 gport
->grid_color
.red
^= gport
->bg_color
.red
;
344 gport
->grid_color
.green
^= gport
->bg_color
.green
;
345 gport
->grid_color
.blue
^= gport
->bg_color
.blue
;
349 ghid_set_special_colors (HID_Attribute
* ha
)
351 if (!ha
->name
|| !ha
->value
)
353 if (!strcmp (ha
->name
, "background-color"))
355 ghid_map_color_string (*(char **) ha
->value
, &gport
->bg_color
);
356 set_special_grid_color ();
358 else if (!strcmp (ha
->name
, "off-limit-color"))
360 ghid_map_color_string (*(char **) ha
->value
, &gport
->offlimits_color
);
362 else if (!strcmp (ha
->name
, "grid-color"))
364 ghid_map_color_string (*(char **) ha
->value
, &gport
->grid_color
);
365 set_special_grid_color ();
379 set_gl_color_for_gc (hidGC gc
)
381 render_priv
*priv
= gport
->render_priv
;
382 static void *cache
= NULL
;
387 if (priv
->current_colorname
!= NULL
&&
388 strcmp (priv
->current_colorname
, gc
->colorname
) == 0 &&
389 priv
->current_alpha_mult
== gc
->alpha_mult
)
392 free (priv
->current_colorname
);
393 priv
->current_colorname
= strdup (gc
->colorname
);
394 priv
->current_alpha_mult
= gc
->alpha_mult
;
396 if (gport
->colormap
== NULL
)
397 gport
->colormap
= gtk_widget_get_colormap (gport
->top_window
);
398 if (strcmp (gc
->colorname
, "erase") == 0)
400 r
= gport
->bg_color
.red
/ 65535.;
401 g
= gport
->bg_color
.green
/ 65535.;
402 b
= gport
->bg_color
.blue
/ 65535.;
405 else if (strcmp (gc
->colorname
, "drill") == 0)
407 r
= gport
->offlimits_color
.red
/ 65535.;
408 g
= gport
->offlimits_color
.green
/ 65535.;
409 b
= gport
->offlimits_color
.blue
/ 65535.;
414 if (hid_cache_color (0, gc
->colorname
, &cval
, &cache
))
415 cc
= (ColorCache
*) cval
.ptr
;
418 cc
= (ColorCache
*) malloc (sizeof (ColorCache
));
419 memset (cc
, 0, sizeof (*cc
));
421 hid_cache_color (1, gc
->colorname
, &cval
, &cache
);
426 if (gdk_color_parse (gc
->colorname
, &cc
->color
))
427 gdk_color_alloc (gport
->colormap
, &cc
->color
);
429 gdk_color_white (gport
->colormap
, &cc
->color
);
430 cc
->red
= cc
->color
.red
/ 65535.;
431 cc
->green
= cc
->color
.green
/ 65535.;
432 cc
->blue
= cc
->color
.blue
/ 65535.;
443 if (!priv
->trans_lines
)
446 if (g
> maxi
) maxi
= g
;
447 if (b
> maxi
) maxi
= b
;
448 mult
= MIN (1 / a
, 1 / maxi
);
456 if(!priv
->in_context
)
459 hidgl_flush_triangles (&buffer
);
460 glColor4d (r
, g
, b
, a
);
464 ghid_set_color (hidGC gc
, const char *name
)
466 gc
->colorname
= name
;
467 set_gl_color_for_gc (gc
);
471 ghid_set_alpha_mult (hidGC gc
, double alpha_mult
)
473 gc
->alpha_mult
= alpha_mult
;
474 set_gl_color_for_gc (gc
);
478 ghid_set_line_cap (hidGC gc
, EndCapStyle style
)
484 ghid_set_line_width (hidGC gc
, Coord width
)
491 ghid_set_draw_xor (hidGC gc
, int xor)
493 /* NOT IMPLEMENTED */
495 /* Only presently called when setting up a crosshair GC.
496 * We manage our own drawing model for that anyway. */
500 ghid_set_draw_faded (hidGC gc
, int faded
)
502 printf ("ghid_set_draw_faded(%p,%d) -- not implemented\n", gc
, faded
);
506 ghid_set_line_cap_angle (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
508 printf ("ghid_set_line_cap_angle() -- not implemented\n");
512 ghid_invalidate_current_gc (void)
520 if (gc
->me_pointer
!= &ghid_hid
)
522 fprintf (stderr
, "Fatal: GC from another HID passed to GTK HID\n");
526 if (current_gc
== gc
)
531 set_gl_color_for_gc (gc
);
536 ghid_draw_line (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
540 hidgl_draw_line (gc
->cap
, gc
->width
, x1
, y1
, x2
, y2
, gport
->view
.coord_per_px
);
544 ghid_draw_arc (hidGC gc
, Coord cx
, Coord cy
, Coord xradius
, Coord yradius
,
545 Angle start_angle
, Angle delta_angle
)
549 hidgl_draw_arc (gc
->width
, cx
, cy
, xradius
, yradius
,
550 start_angle
, delta_angle
, gport
->view
.coord_per_px
);
554 ghid_draw_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
558 hidgl_draw_rect (x1
, y1
, x2
, y2
);
563 ghid_fill_circle (hidGC gc
, Coord cx
, Coord cy
, Coord radius
)
567 hidgl_fill_circle (cx
, cy
, radius
, gport
->view
.coord_per_px
);
572 ghid_fill_polygon (hidGC gc
, int n_coords
, Coord
*x
, Coord
*y
)
576 hidgl_fill_polygon (n_coords
, x
, y
);
580 ghid_fill_pcb_polygon (hidGC gc
, PolygonType
*poly
, const BoxType
*clip_box
)
584 hidgl_fill_pcb_polygon (poly
, clip_box
, gport
->view
.coord_per_px
);
588 ghid_thindraw_pcb_polygon (hidGC gc
, PolygonType
*poly
, const BoxType
*clip_box
)
590 common_thindraw_pcb_polygon (gc
, poly
, clip_box
);
591 ghid_set_alpha_mult (gc
, 0.25);
592 gui
->graphics
->fill_pcb_polygon (gc
, poly
, clip_box
);
593 ghid_set_alpha_mult (gc
, 1.0);
597 ghid_fill_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
601 hidgl_fill_rect (x1
, y1
, x2
, y2
);
605 ghid_invalidate_lr (int left
, int right
, int top
, int bottom
)
607 ghid_invalidate_all ();
610 #define MAX_ELAPSED (50. / 1000.) /* 50ms */
612 ghid_invalidate_all ()
614 render_priv
*priv
= gport
->render_priv
;
615 double elapsed
= g_timer_elapsed (priv
->time_since_expose
, NULL
);
617 ghid_draw_area_update (gport
, NULL
);
619 if (elapsed
> MAX_ELAPSED
)
620 gdk_window_process_all_updates ();
624 ghid_notify_crosshair_change (bool changes_complete
)
626 /* We sometimes get called before the GUI is up */
627 if (gport
->drawing_area
== NULL
)
630 /* FIXME: We could just invalidate the bounds of the crosshair attached objects? */
631 ghid_invalidate_all ();
635 ghid_notify_mark_change (bool changes_complete
)
637 /* We sometimes get called before the GUI is up */
638 if (gport
->drawing_area
== NULL
)
641 /* FIXME: We could just invalidate the bounds of the mark? */
642 ghid_invalidate_all ();
646 draw_right_cross (gint x
, gint y
, gint z
)
648 glVertex3i (x
, 0, z
);
649 glVertex3i (x
, PCB
->MaxHeight
, z
);
650 glVertex3i (0, y
, z
);
651 glVertex3i (PCB
->MaxWidth
, y
, z
);
655 draw_slanted_cross (gint x
, gint y
, gint z
)
659 x0
= x
+ (PCB
->MaxHeight
- y
);
660 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
662 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
663 y0
= y
+ (PCB
->MaxWidth
- x
);
664 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
666 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
667 glVertex3i (x0
, y0
, z
);
668 glVertex3i (x1
, y1
, z
);
670 x0
= x
- (PCB
->MaxHeight
- y
);
671 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
673 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
675 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
676 y1
= y
- (PCB
->MaxWidth
- x
);
677 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
678 glVertex3i (x0
, y0
, z
);
679 glVertex3i (x1
, y1
, z
);
683 draw_dozen_cross (gint x
, gint y
, gint z
)
686 gdouble tan60
= sqrt (3);
688 x0
= x
+ (PCB
->MaxHeight
- y
) / tan60
;
689 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
691 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
692 y0
= y
+ (PCB
->MaxWidth
- x
) * tan60
;
693 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
695 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
696 glVertex3i (x0
, y0
, z
);
697 glVertex3i (x1
, y1
, z
);
699 x0
= x
+ (PCB
->MaxHeight
- y
) * tan60
;
700 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
702 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
703 y0
= y
+ (PCB
->MaxWidth
- x
) / tan60
;
704 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
706 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
707 glVertex3i (x0
, y0
, z
);
708 glVertex3i (x1
, y1
, z
);
710 x0
= x
- (PCB
->MaxHeight
- y
) / tan60
;
711 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
713 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
715 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
716 y1
= y
- (PCB
->MaxWidth
- x
) * tan60
;
717 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
718 glVertex3i (x0
, y0
, z
);
719 glVertex3i (x1
, y1
, z
);
721 x0
= x
- (PCB
->MaxHeight
- y
) * tan60
;
722 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
724 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
726 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
727 y1
= y
- (PCB
->MaxWidth
- x
) / tan60
;
728 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
729 glVertex3i (x0
, y0
, z
);
730 glVertex3i (x1
, y1
, z
);
734 draw_crosshair (render_priv
*priv
)
737 static int done_once
= 0;
738 static GdkColor cross_color
;
743 /* FIXME: when CrossColor changed from config */
744 ghid_map_color_string (Settings
.CrossColor
, &cross_color
);
747 x
= gport
->crosshair_x
;
748 y
= gport
->crosshair_y
;
751 glEnable (GL_COLOR_LOGIC_OP
);
754 glColor3f (cross_color
.red
/ 65535.,
755 cross_color
.green
/ 65535.,
756 cross_color
.blue
/ 65535.);
760 draw_right_cross (x
, y
, z
);
761 if (Crosshair
.shape
== Union_Jack_Crosshair_Shape
)
762 draw_slanted_cross (x
, y
, z
);
763 if (Crosshair
.shape
== Dozen_Crosshair_Shape
)
764 draw_dozen_cross (x
, y
, z
);
768 glDisable (GL_COLOR_LOGIC_OP
);
772 ghid_init_renderer (int *argc
, char ***argv
, GHidPort
*port
)
776 port
->render_priv
= priv
= g_new0 (render_priv
, 1);
777 port
->render_priv
->crosshair_gc
= gui
->graphics
->make_gc ();
779 priv
->time_since_expose
= g_timer_new ();
781 gtk_gl_init(argc
, argv
);
783 /* setup GL-context */
784 priv
->glconfig
= gdk_gl_config_new_by_mode (GDK_GL_MODE_RGBA
|
785 GDK_GL_MODE_STENCIL
|
789 printf ("Could not setup GL-context!\n");
790 return; /* Should we abort? */
793 /* Setup HID function pointers specific to the GL renderer*/
794 ghid_hid
.end_layer
= ghid_end_layer
;
795 ghid_graphics
.fill_pcb_polygon
= ghid_fill_pcb_polygon
;
796 ghid_graphics
.thindraw_pcb_polygon
= ghid_thindraw_pcb_polygon
;
800 ghid_shutdown_renderer (GHidPort
*port
)
802 render_priv
*priv
= port
->render_priv
;
804 gui
->graphics
->destroy_gc (priv
->crosshair_gc
);
805 ghid_cancel_lead_user ();
806 g_free (port
->render_priv
);
807 port
->render_priv
= NULL
;
811 ghid_init_drawing_widget (GtkWidget
*widget
, GHidPort
*port
)
813 render_priv
*priv
= port
->render_priv
;
815 gtk_widget_set_gl_capability (widget
,
823 ghid_drawing_area_configure_hook (GHidPort
*port
)
828 ghid_start_drawing (GHidPort
*port
, GtkWidget
*widget
)
830 GdkGLContext
*pGlContext
= gtk_widget_get_gl_context (widget
);
831 GdkGLDrawable
*pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
833 /* make GL-context "current" */
834 if (!gdk_gl_drawable_gl_begin (pGlDrawable
, pGlContext
))
837 port
->render_priv
->in_context
= true;
843 ghid_end_drawing (GHidPort
*port
, GtkWidget
*widget
)
845 GdkGLDrawable
*pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
847 if (gdk_gl_drawable_is_double_buffered (pGlDrawable
))
848 gdk_gl_drawable_swap_buffers (pGlDrawable
);
852 port
->render_priv
->in_context
= false;
854 /* end drawing to current GL-context */
855 gdk_gl_drawable_gl_end (pGlDrawable
);
859 ghid_screen_update (void)
865 ghid_drawing_area_expose_cb (GtkWidget
*widget
,
869 render_priv
*priv
= port
->render_priv
;
870 GtkAllocation allocation
;
878 gtk_widget_get_allocation (widget
, &allocation
);
880 ghid_start_drawing (port
, widget
);
881 hidgl_start_render ();
883 /* If we don't have any stencil bits available,
884 we can't use the hidgl polygon drawing routine */
885 /* TODO: We could use the GLU tessellator though */
886 if (hidgl_stencil_bits() == 0)
887 ghid_graphics
.fill_pcb_polygon
= common_fill_pcb_polygon
;
890 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
892 glViewport (0, 0, allocation
.width
, allocation
.height
);
894 glEnable (GL_SCISSOR_TEST
);
895 glScissor (ev
->area
.x
,
896 allocation
.height
- ev
->area
.height
- ev
->area
.y
,
897 ev
->area
.width
, ev
->area
.height
);
899 glMatrixMode (GL_PROJECTION
);
901 glOrtho (0, allocation
.width
, allocation
.height
, 0, -100000, 100000);
902 glMatrixMode (GL_MODELVIEW
);
904 glTranslatef (widget
->allocation
.width
/ 2., widget
->allocation
.height
/ 2., 0);
905 glMultMatrixf ((GLfloat
*)view_matrix
);
906 glTranslatef (-widget
->allocation
.width
/ 2., -widget
->allocation
.height
/ 2., 0);
907 glScalef ((port
->view
.flip_x
? -1. : 1.) / port
->view
.coord_per_px
,
908 (port
->view
.flip_y
? -1. : 1.) / port
->view
.coord_per_px
,
909 ((port
->view
.flip_x
== port
->view
.flip_y
) ? 1. : -1.) / port
->view
.coord_per_px
);
910 glTranslatef (port
->view
.flip_x
? port
->view
.x0
- PCB
->MaxWidth
:
912 port
->view
.flip_y
? port
->view
.y0
- PCB
->MaxHeight
:
914 glGetFloatv (GL_MODELVIEW_MATRIX
, (GLfloat
*)last_modelview_matrix
);
916 glEnable (GL_STENCIL_TEST
);
917 glClearColor (port
->offlimits_color
.red
/ 65535.,
918 port
->offlimits_color
.green
/ 65535.,
919 port
->offlimits_color
.blue
/ 65535.,
923 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
924 hidgl_reset_stencil_usage ();
926 /* Disable the stencil test until we need it - otherwise it gets dirty */
927 glDisable (GL_STENCIL_TEST
);
929 glStencilFunc (GL_ALWAYS
, 0, 0);
931 /* Test the 8 corners of a cube spanning the event */
932 min_depth
= -50; /* FIXME */
933 max_depth
= 0; /* FIXME */
935 ghid_unproject_to_z_plane (ev
->area
.x
,
937 min_depth
, &new_x
, &new_y
);
938 max_x
= min_x
= new_x
;
939 max_y
= min_y
= new_y
;
941 ghid_unproject_to_z_plane (ev
->area
.x
,
943 max_depth
, &new_x
, &new_y
);
944 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
945 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
948 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
,
950 min_depth
, &new_x
, &new_y
);
951 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
952 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
954 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
, ev
->area
.y
,
955 max_depth
, &new_x
, &new_y
);
956 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
957 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
960 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
,
961 ev
->area
.y
+ ev
->area
.height
,
962 min_depth
, &new_x
, &new_y
);
963 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
964 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
966 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
,
967 ev
->area
.y
+ ev
->area
.height
,
968 max_depth
, &new_x
, &new_y
);
969 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
970 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
973 ghid_unproject_to_z_plane (ev
->area
.x
,
974 ev
->area
.y
+ ev
->area
.height
,
977 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
978 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
980 ghid_unproject_to_z_plane (ev
->area
.x
,
981 ev
->area
.y
+ ev
->area
.height
,
984 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
985 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
987 region
.X1
= min_x
; region
.X2
= max_x
+ 1;
988 region
.Y1
= min_y
; region
.Y2
= max_y
+ 1;
990 region
.X1
= MAX (0, MIN (PCB
->MaxWidth
, region
.X1
));
991 region
.X2
= MAX (0, MIN (PCB
->MaxWidth
, region
.X2
));
992 region
.Y1
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y1
));
993 region
.Y2
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y2
));
995 glColor3f (port
->bg_color
.red
/ 65535.,
996 port
->bg_color
.green
/ 65535.,
997 port
->bg_color
.blue
/ 65535.);
1000 glVertex3i (0, 0, -50);
1001 glVertex3i (PCB
->MaxWidth
, 0, -50);
1002 glVertex3i (PCB
->MaxWidth
, PCB
->MaxHeight
, -50);
1003 glVertex3i (0, PCB
->MaxHeight
, -50);
1006 ghid_draw_bg_image ();
1008 ghid_invalidate_current_gc ();
1009 hid_expose_callback (&ghid_hid
, ®ion
, 0);
1010 hidgl_flush_triangles (&buffer
);
1012 ghid_draw_grid (®ion
);
1014 ghid_invalidate_current_gc ();
1016 DrawAttached (priv
->crosshair_gc
);
1017 DrawMark (priv
->crosshair_gc
);
1018 hidgl_flush_triangles (&buffer
);
1020 draw_crosshair (priv
);
1021 hidgl_flush_triangles (&buffer
);
1023 draw_lead_user (priv
);
1025 hidgl_finish_render ();
1026 ghid_end_drawing (port
, widget
);
1028 g_timer_start (priv
->time_since_expose
);
1033 /* This realize callback is used to work around a crash bug in some mesa
1034 * versions (observed on a machine running the intel i965 driver. It isn't
1035 * obvious why it helps, but somehow fiddling with the GL context here solves
1036 * the issue. The problem appears to have been fixed in recent mesa versions.
1039 ghid_port_drawing_realize_cb (GtkWidget
*widget
, gpointer data
)
1041 GdkGLContext
*glcontext
= gtk_widget_get_gl_context (widget
);
1042 GdkGLDrawable
*gldrawable
= gtk_widget_get_gl_drawable (widget
);
1044 if (!gdk_gl_drawable_gl_begin (gldrawable
, glcontext
))
1047 gdk_gl_drawable_gl_end (gldrawable
);
1052 ghid_pinout_preview_expose (GtkWidget
*widget
,
1055 GhidPinoutPreview
*pinout
= GHID_PINOUT_PREVIEW (widget
);
1056 GtkAllocation allocation
;
1057 view_data save_view
;
1058 int save_width
, save_height
;
1059 Coord save_max_width
;
1060 Coord save_max_height
;
1063 save_view
= gport
->view
;
1064 save_width
= gport
->width
;
1065 save_height
= gport
->height
;
1066 save_max_width
= PCB
->MaxWidth
;
1067 save_max_height
= PCB
->MaxHeight
;
1069 /* Setup zoom factor for drawing routines */
1071 gtk_widget_get_allocation (widget
, &allocation
);
1072 xz
= (double) pinout
->x_max
/ allocation
.width
;
1073 yz
= (double) pinout
->y_max
/ allocation
.height
;
1075 gport
->view
.coord_per_px
= xz
;
1077 gport
->view
.coord_per_px
= yz
;
1079 gport
->width
= allocation
.width
;
1080 gport
->height
= allocation
.height
;
1081 gport
->view
.width
= allocation
.width
* gport
->view
.coord_per_px
;
1082 gport
->view
.height
= allocation
.height
* gport
->view
.coord_per_px
;
1083 gport
->view
.x0
= (pinout
->x_max
- gport
->view
.width
) / 2;
1084 gport
->view
.y0
= (pinout
->y_max
- gport
->view
.height
) / 2;
1085 PCB
->MaxWidth
= pinout
->x_max
;
1086 PCB
->MaxHeight
= pinout
->y_max
;
1088 ghid_start_drawing (gport
, widget
);
1089 hidgl_start_render ();
1091 #if 0 /* We disable alpha blending here, as hid_expose_callback() does not
1092 * call set_layer() as appropriate for us to sub-composite rendering
1093 * from each layer when drawing a single element. If we leave alpha-
1094 * blending on, it means text and overlapping pads are rendered ugly.
1097 glEnable (GL_BLEND
);
1098 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1101 glViewport (0, 0, allocation
.width
, allocation
.height
);
1103 #if 0 /* We disable the scissor test here, as it is interacting badly with
1104 * being handed expose events which don't cover the whole window.
1105 * As we have a double-buffered GL window, we end up with unintialised
1106 * contents remaining in the unpainted areas (outside the scissor
1107 * region), and these are being flipped onto the screen.
1109 * The debugging code below shows multiple expose events when the
1110 * window is shown the first time, some of which are very small.
1112 * XXX: There is clearly a perforamnce issue here, in that we may
1113 * be rendering the preview more times, and over a larger area
1114 * than is really required.
1117 glEnable (GL_SCISSOR_TEST
);
1118 glScissor (ev
->area
.x
,
1119 allocation
.height
- ev
->area
.height
- ev
->area
.y
,
1120 ev
->area
.width
, ev
->area
.height
);
1124 printf ("EVT: %i, %i, w=%i, h=%i, Scissor setup: glScissor (%f, %f, %f, %f);\n",
1125 ev
->area
.x
, ev
->area
.y
, ev
->area
.width
, ev
->area
.height
,
1127 (double)(allocation
.height
- ev
->area
.height
- ev
->area
.y
),
1128 (double)ev
->area
.width
,
1129 (double)ev
->area
.height
);
1132 glMatrixMode (GL_PROJECTION
);
1134 glOrtho (0, allocation
.width
, allocation
.height
, 0, -100000, 100000);
1135 glMatrixMode (GL_MODELVIEW
);
1137 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
1139 glClearColor (gport
->bg_color
.red
/ 65535.,
1140 gport
->bg_color
.green
/ 65535.,
1141 gport
->bg_color
.blue
/ 65535.,
1145 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
1146 hidgl_reset_stencil_usage ();
1148 /* Disable the stencil test until we need it - otherwise it gets dirty */
1149 glDisable (GL_STENCIL_TEST
);
1151 glStencilFunc (GL_ALWAYS
, 0, 0);
1153 /* call the drawing routine */
1154 ghid_invalidate_current_gc ();
1156 glScalef ((gport
->view
.flip_x
? -1. : 1.) / gport
->view
.coord_per_px
,
1157 (gport
->view
.flip_y
? -1. : 1.) / gport
->view
.coord_per_px
,
1158 ((gport
->view
.flip_x
== gport
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
1159 glTranslatef (gport
->view
.flip_x
? gport
->view
.x0
- PCB
->MaxWidth
:
1161 gport
->view
.flip_y
? gport
->view
.y0
- PCB
->MaxHeight
:
1162 -gport
->view
.y0
, 0);
1164 hid_expose_callback (&ghid_hid
, NULL
, pinout
->element
);
1165 hidgl_flush_triangles (&buffer
);
1168 hidgl_finish_render ();
1169 ghid_end_drawing (gport
, widget
);
1171 gport
->view
= save_view
;
1172 gport
->width
= save_width
;
1173 gport
->height
= save_height
;
1174 PCB
->MaxWidth
= save_max_width
;
1175 PCB
->MaxHeight
= save_max_height
;
1182 ghid_render_pixmap (int cx
, int cy
, double zoom
, int width
, int height
, int depth
)
1184 GdkGLConfig
*glconfig
;
1186 GdkGLPixmap
*glpixmap
;
1187 GdkGLContext
* glcontext
;
1188 GdkGLDrawable
* gldrawable
;
1189 view_data save_view
;
1190 int save_width
, save_height
;
1193 save_view
= gport
->view
;
1194 save_width
= gport
->width
;
1195 save_height
= gport
->height
;
1197 /* Setup rendering context for drawing routines
1200 glconfig
= gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB
|
1201 GDK_GL_MODE_STENCIL
|
1202 GDK_GL_MODE_SINGLE
);
1204 pixmap
= gdk_pixmap_new (NULL
, width
, height
, depth
);
1205 glpixmap
= gdk_pixmap_set_gl_capability (pixmap
, glconfig
, NULL
);
1206 gldrawable
= GDK_GL_DRAWABLE (glpixmap
);
1207 glcontext
= gdk_gl_context_new (gldrawable
, NULL
, TRUE
, GDK_GL_RGBA_TYPE
);
1209 /* Setup zoom factor for drawing routines */
1211 gport
->view
.coord_per_px
= zoom
;
1212 gport
->width
= width
;
1213 gport
->height
= height
;
1214 gport
->view
.width
= width
* gport
->view
.coord_per_px
;
1215 gport
->view
.height
= height
* gport
->view
.coord_per_px
;
1216 gport
->view
.x0
= gport
->view
.flip_x
? PCB
->MaxWidth
- cx
: cx
;
1217 gport
->view
.x0
-= gport
->view
.height
/ 2;
1218 gport
->view
.y0
= gport
->view
.flip_y
? PCB
->MaxHeight
- cy
: cy
;
1219 gport
->view
.y0
-= gport
->view
.width
/ 2;
1221 /* make GL-context "current" */
1222 if (!gdk_gl_drawable_gl_begin (gldrawable
, glcontext
)) {
1225 hidgl_start_render ();
1226 gport
->render_priv
->in_context
= true;
1228 glEnable (GL_BLEND
);
1229 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1231 glViewport (0, 0, width
, height
);
1233 glEnable (GL_SCISSOR_TEST
);
1234 glScissor (0, 0, width
, height
);
1236 glMatrixMode (GL_PROJECTION
);
1238 glOrtho (0, width
, height
, 0, -100000, 100000);
1239 glMatrixMode (GL_MODELVIEW
);
1241 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
1243 glClearColor (gport
->bg_color
.red
/ 65535.,
1244 gport
->bg_color
.green
/ 65535.,
1245 gport
->bg_color
.blue
/ 65535.,
1249 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
1250 hidgl_reset_stencil_usage ();
1252 /* Disable the stencil test until we need it - otherwise it gets dirty */
1253 glDisable (GL_STENCIL_TEST
);
1255 glStencilFunc (GL_ALWAYS
, 0, 0);
1257 /* call the drawing routine */
1258 ghid_invalidate_current_gc ();
1260 glScalef ((gport
->view
.flip_x
? -1. : 1.) / gport
->view
.coord_per_px
,
1261 (gport
->view
.flip_y
? -1. : 1.) / gport
->view
.coord_per_px
,
1262 ((gport
->view
.flip_x
== gport
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
1263 glTranslatef (gport
->view
.flip_x
? gport
->view
.x0
- PCB
->MaxWidth
:
1265 gport
->view
.flip_y
? gport
->view
.y0
- PCB
->MaxHeight
:
1266 -gport
->view
.y0
, 0);
1268 region
.X1
= MIN(Px(0), Px(gport
->width
+ 1));
1269 region
.Y1
= MIN(Py(0), Py(gport
->height
+ 1));
1270 region
.X2
= MAX(Px(0), Px(gport
->width
+ 1));
1271 region
.Y2
= MAX(Py(0), Py(gport
->height
+ 1));
1273 region
.X1
= MAX (0, MIN (PCB
->MaxWidth
, region
.X1
));
1274 region
.X2
= MAX (0, MIN (PCB
->MaxWidth
, region
.X2
));
1275 region
.Y1
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y1
));
1276 region
.Y2
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y2
));
1278 hid_expose_callback (&ghid_hid
, ®ion
, NULL
);
1279 hidgl_flush_triangles (&buffer
);
1284 hidgl_finish_render ();
1286 /* end drawing to current GL-context */
1287 gport
->render_priv
->in_context
= false;
1288 gdk_gl_drawable_gl_end (gldrawable
);
1290 gdk_pixmap_unset_gl_capability (pixmap
);
1292 g_object_unref (glconfig
);
1293 g_object_unref (glcontext
);
1295 gport
->view
= save_view
;
1296 gport
->width
= save_width
;
1297 gport
->height
= save_height
;
1303 ghid_request_debug_draw (void)
1305 GHidPort
*port
= gport
;
1306 GtkWidget
*widget
= port
->drawing_area
;
1307 GtkAllocation allocation
;
1309 gtk_widget_get_allocation (widget
, &allocation
);
1311 ghid_start_drawing (port
, widget
);
1312 hidgl_start_render ();
1314 glViewport (0, 0, allocation
.width
, allocation
.height
);
1316 glMatrixMode (GL_PROJECTION
);
1318 glOrtho (0, allocation
.width
, allocation
.height
, 0, 0, 100);
1319 glMatrixMode (GL_MODELVIEW
);
1321 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
1323 ghid_invalidate_current_gc ();
1325 /* Setup stenciling */
1326 glDisable (GL_STENCIL_TEST
);
1329 glScalef ((port
->view
.flip_x
? -1. : 1.) / port
->view
.coord_per_px
,
1330 (port
->view
.flip_y
? -1. : 1.) / port
->view
.coord_per_px
,
1331 ((gport
->view
.flip_x
== port
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
1332 glTranslatef (port
->view
.flip_x
? port
->view
.x0
- PCB
->MaxWidth
:
1334 port
->view
.flip_y
? port
->view
.y0
- PCB
->MaxHeight
:
1337 return ghid_hid
.graphics
;
1341 ghid_flush_debug_draw (void)
1343 GtkWidget
*widget
= gport
->drawing_area
;
1344 GdkGLDrawable
*pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
1346 hidgl_flush_triangles (&buffer
);
1348 if (gdk_gl_drawable_is_double_buffered (pGlDrawable
))
1349 gdk_gl_drawable_swap_buffers (pGlDrawable
);
1355 ghid_finish_debug_draw (void)
1357 hidgl_flush_triangles (&buffer
);
1360 hidgl_finish_render ();
1361 ghid_end_drawing (gport
, gport
->drawing_area
);
1365 determinant_2x2 (float m
[2][2])
1368 det
= m
[0][0] * m
[1][1] -
1375 determinant_4x4 (float m
[4][4])
1378 det
= m
[0][3] * m
[1][2] * m
[2][1] * m
[3][0]-m
[0][2] * m
[1][3] * m
[2][1] * m
[3][0] -
1379 m
[0][3] * m
[1][1] * m
[2][2] * m
[3][0]+m
[0][1] * m
[1][3] * m
[2][2] * m
[3][0] +
1380 m
[0][2] * m
[1][1] * m
[2][3] * m
[3][0]-m
[0][1] * m
[1][2] * m
[2][3] * m
[3][0] -
1381 m
[0][3] * m
[1][2] * m
[2][0] * m
[3][1]+m
[0][2] * m
[1][3] * m
[2][0] * m
[3][1] +
1382 m
[0][3] * m
[1][0] * m
[2][2] * m
[3][1]-m
[0][0] * m
[1][3] * m
[2][2] * m
[3][1] -
1383 m
[0][2] * m
[1][0] * m
[2][3] * m
[3][1]+m
[0][0] * m
[1][2] * m
[2][3] * m
[3][1] +
1384 m
[0][3] * m
[1][1] * m
[2][0] * m
[3][2]-m
[0][1] * m
[1][3] * m
[2][0] * m
[3][2] -
1385 m
[0][3] * m
[1][0] * m
[2][1] * m
[3][2]+m
[0][0] * m
[1][3] * m
[2][1] * m
[3][2] +
1386 m
[0][1] * m
[1][0] * m
[2][3] * m
[3][2]-m
[0][0] * m
[1][1] * m
[2][3] * m
[3][2] -
1387 m
[0][2] * m
[1][1] * m
[2][0] * m
[3][3]+m
[0][1] * m
[1][2] * m
[2][0] * m
[3][3] +
1388 m
[0][2] * m
[1][0] * m
[2][1] * m
[3][3]-m
[0][0] * m
[1][2] * m
[2][1] * m
[3][3] -
1389 m
[0][1] * m
[1][0] * m
[2][2] * m
[3][3]+m
[0][0] * m
[1][1] * m
[2][2] * m
[3][3];
1395 invert_2x2 (float m
[2][2], float out
[2][2])
1397 float scale
= 1 / determinant_2x2 (m
);
1398 out
[0][0] = m
[1][1] * scale
;
1399 out
[0][1] = -m
[0][1] * scale
;
1400 out
[1][0] = -m
[1][0] * scale
;
1401 out
[1][1] = m
[0][0] * scale
;
1406 invert_4x4 (float m
[4][4], float out
[4][4])
1408 float scale
= 1 / determinant_4x4 (m
);
1410 out
[0][0] = (m
[1][2] * m
[2][3] * m
[3][1] - m
[1][3] * m
[2][2] * m
[3][1] +
1411 m
[1][3] * m
[2][1] * m
[3][2] - m
[1][1] * m
[2][3] * m
[3][2] -
1412 m
[1][2] * m
[2][1] * m
[3][3] + m
[1][1] * m
[2][2] * m
[3][3]) * scale
;
1413 out
[0][1] = (m
[0][3] * m
[2][2] * m
[3][1] - m
[0][2] * m
[2][3] * m
[3][1] -
1414 m
[0][3] * m
[2][1] * m
[3][2] + m
[0][1] * m
[2][3] * m
[3][2] +
1415 m
[0][2] * m
[2][1] * m
[3][3] - m
[0][1] * m
[2][2] * m
[3][3]) * scale
;
1416 out
[0][2] = (m
[0][2] * m
[1][3] * m
[3][1] - m
[0][3] * m
[1][2] * m
[3][1] +
1417 m
[0][3] * m
[1][1] * m
[3][2] - m
[0][1] * m
[1][3] * m
[3][2] -
1418 m
[0][2] * m
[1][1] * m
[3][3] + m
[0][1] * m
[1][2] * m
[3][3]) * scale
;
1419 out
[0][3] = (m
[0][3] * m
[1][2] * m
[2][1] - m
[0][2] * m
[1][3] * m
[2][1] -
1420 m
[0][3] * m
[1][1] * m
[2][2] + m
[0][1] * m
[1][3] * m
[2][2] +
1421 m
[0][2] * m
[1][1] * m
[2][3] - m
[0][1] * m
[1][2] * m
[2][3]) * scale
;
1422 out
[1][0] = (m
[1][3] * m
[2][2] * m
[3][0] - m
[1][2] * m
[2][3] * m
[3][0] -
1423 m
[1][3] * m
[2][0] * m
[3][2] + m
[1][0] * m
[2][3] * m
[3][2] +
1424 m
[1][2] * m
[2][0] * m
[3][3] - m
[1][0] * m
[2][2] * m
[3][3]) * scale
;
1425 out
[1][1] = (m
[0][2] * m
[2][3] * m
[3][0] - m
[0][3] * m
[2][2] * m
[3][0] +
1426 m
[0][3] * m
[2][0] * m
[3][2] - m
[0][0] * m
[2][3] * m
[3][2] -
1427 m
[0][2] * m
[2][0] * m
[3][3] + m
[0][0] * m
[2][2] * m
[3][3]) * scale
;
1428 out
[1][2] = (m
[0][3] * m
[1][2] * m
[3][0] - m
[0][2] * m
[1][3] * m
[3][0] -
1429 m
[0][3] * m
[1][0] * m
[3][2] + m
[0][0] * m
[1][3] * m
[3][2] +
1430 m
[0][2] * m
[1][0] * m
[3][3] - m
[0][0] * m
[1][2] * m
[3][3]) * scale
;
1431 out
[1][3] = (m
[0][2] * m
[1][3] * m
[2][0] - m
[0][3] * m
[1][2] * m
[2][0] +
1432 m
[0][3] * m
[1][0] * m
[2][2] - m
[0][0] * m
[1][3] * m
[2][2] -
1433 m
[0][2] * m
[1][0] * m
[2][3] + m
[0][0] * m
[1][2] * m
[2][3]) * scale
;
1434 out
[2][0] = (m
[1][1] * m
[2][3] * m
[3][0] - m
[1][3] * m
[2][1] * m
[3][0] +
1435 m
[1][3] * m
[2][0] * m
[3][1] - m
[1][0] * m
[2][3] * m
[3][1] -
1436 m
[1][1] * m
[2][0] * m
[3][3] + m
[1][0] * m
[2][1] * m
[3][3]) * scale
;
1437 out
[2][1] = (m
[0][3] * m
[2][1] * m
[3][0] - m
[0][1] * m
[2][3] * m
[3][0] -
1438 m
[0][3] * m
[2][0] * m
[3][1] + m
[0][0] * m
[2][3] * m
[3][1] +
1439 m
[0][1] * m
[2][0] * m
[3][3] - m
[0][0] * m
[2][1] * m
[3][3]) * scale
;
1440 out
[2][2] = (m
[0][1] * m
[1][3] * m
[3][0] - m
[0][3] * m
[1][1] * m
[3][0] +
1441 m
[0][3] * m
[1][0] * m
[3][1] - m
[0][0] * m
[1][3] * m
[3][1] -
1442 m
[0][1] * m
[1][0] * m
[3][3] + m
[0][0] * m
[1][1] * m
[3][3]) * scale
;
1443 out
[2][3] = (m
[0][3] * m
[1][1] * m
[2][0] - m
[0][1] * m
[1][3] * m
[2][0] -
1444 m
[0][3] * m
[1][0] * m
[2][1] + m
[0][0] * m
[1][3] * m
[2][1] +
1445 m
[0][1] * m
[1][0] * m
[2][3] - m
[0][0] * m
[1][1] * m
[2][3]) * scale
;
1446 out
[3][0] = (m
[1][2] * m
[2][1] * m
[3][0] - m
[1][1] * m
[2][2] * m
[3][0] -
1447 m
[1][2] * m
[2][0] * m
[3][1] + m
[1][0] * m
[2][2] * m
[3][1] +
1448 m
[1][1] * m
[2][0] * m
[3][2] - m
[1][0] * m
[2][1] * m
[3][2]) * scale
;
1449 out
[3][1] = (m
[0][1] * m
[2][2] * m
[3][0] - m
[0][2] * m
[2][1] * m
[3][0] +
1450 m
[0][2] * m
[2][0] * m
[3][1] - m
[0][0] * m
[2][2] * m
[3][1] -
1451 m
[0][1] * m
[2][0] * m
[3][2] + m
[0][0] * m
[2][1] * m
[3][2]) * scale
;
1452 out
[3][2] = (m
[0][2] * m
[1][1] * m
[3][0] - m
[0][1] * m
[1][2] * m
[3][0] -
1453 m
[0][2] * m
[1][0] * m
[3][1] + m
[0][0] * m
[1][2] * m
[3][1] +
1454 m
[0][1] * m
[1][0] * m
[3][2] - m
[0][0] * m
[1][1] * m
[3][2]) * scale
;
1455 out
[3][3] = (m
[0][1] * m
[1][2] * m
[2][0] - m
[0][2] * m
[1][1] * m
[2][0] +
1456 m
[0][2] * m
[1][0] * m
[2][1] - m
[0][0] * m
[1][2] * m
[2][1] -
1457 m
[0][1] * m
[1][0] * m
[2][2] + m
[0][0] * m
[1][1] * m
[2][2]) * scale
;
1463 ghid_unproject_to_z_plane (int ex
, int ey
, Coord pcb_z
, Coord
*pcb_x
, Coord
*pcb_y
)
1466 float inv_mat
[2][2];
1470 ex = view_matrix[0][0] * vx +
1471 view_matrix[0][1] * vy +
1472 view_matrix[0][2] * vz +
1473 view_matrix[0][3] * 1;
1474 ey = view_matrix[1][0] * vx +
1475 view_matrix[1][1] * vy +
1476 view_matrix[1][2] * vz +
1477 view_matrix[1][3] * 1;
1478 UNKNOWN ez = view_matrix[2][0] * vx +
1479 view_matrix[2][1] * vy +
1480 view_matrix[2][2] * vz +
1481 view_matrix[2][3] * 1;
1483 ex - view_matrix[0][3] * 1
1484 - view_matrix[0][2] * vz
1485 = view_matrix[0][0] * vx +
1486 view_matrix[0][1] * vy;
1488 ey - view_matrix[1][3] * 1
1489 - view_matrix[1][2] * vz
1490 = view_matrix[1][0] * vx +
1491 view_matrix[1][1] * vy;
1494 /* NB: last_modelview_matrix is transposed in memory! */
1495 x
= (float)ex
- last_modelview_matrix
[3][0] * 1
1496 - last_modelview_matrix
[2][0] * pcb_z
;
1498 y
= (float)ey
- last_modelview_matrix
[3][1] * 1
1499 - last_modelview_matrix
[2][1] * pcb_z
;
1502 x = view_matrix[0][0] * vx +
1503 view_matrix[0][1] * vy;
1505 y = view_matrix[1][0] * vx +
1506 view_matrix[1][1] * vy;
1508 [view_matrix[0][0] view_matrix[0][1]] [vx] = [x]
1509 [view_matrix[1][0] view_matrix[1][1]] [vy] [y]
1512 mat
[0][0] = last_modelview_matrix
[0][0];
1513 mat
[0][1] = last_modelview_matrix
[1][0];
1514 mat
[1][0] = last_modelview_matrix
[0][1];
1515 mat
[1][1] = last_modelview_matrix
[1][1];
1517 /* if (determinant_2x2 (mat) < 0.00001) */
1518 /* printf ("Determinant is quite small\n"); */
1520 invert_2x2 (mat
, inv_mat
);
1522 *pcb_x
= (int)(inv_mat
[0][0] * x
+ inv_mat
[0][1] * y
);
1523 *pcb_y
= (int)(inv_mat
[1][0] * x
+ inv_mat
[1][1] * y
);
1528 ghid_event_to_pcb_coords (int event_x
, int event_y
, Coord
*pcb_x
, Coord
*pcb_y
)
1530 ghid_unproject_to_z_plane (event_x
, event_y
, 0, pcb_x
, pcb_y
);
1536 ghid_pcb_to_event_coords (Coord pcb_x
, Coord pcb_y
, int *event_x
, int *event_y
)
1538 /* NB: last_modelview_matrix is transposed in memory */
1539 float w
= last_modelview_matrix
[0][3] * (float)pcb_x
+
1540 last_modelview_matrix
[1][3] * (float)pcb_y
+
1541 last_modelview_matrix
[2][3] * 0. +
1542 last_modelview_matrix
[3][3] * 1.;
1544 *event_x
= (last_modelview_matrix
[0][0] * (float)pcb_x
+
1545 last_modelview_matrix
[1][0] * (float)pcb_y
+
1546 last_modelview_matrix
[2][0] * 0. +
1547 last_modelview_matrix
[3][0] * 1.) / w
;
1548 *event_y
= (last_modelview_matrix
[0][1] * (float)pcb_x
+
1549 last_modelview_matrix
[1][1] * (float)pcb_y
+
1550 last_modelview_matrix
[2][1] * 0. +
1551 last_modelview_matrix
[3][1] * 1.) / w
;
1557 ghid_view_2d (void *ball
, gboolean view_2d
, gpointer userdata
)
1559 global_view_2d
= view_2d
;
1560 ghid_invalidate_all ();
1564 ghid_port_rotate (void *ball
, float *quarternion
, gpointer userdata
)
1570 build_rotmatrix (view_matrix
, quarternion
);
1573 for (row
= 0; row
< 4; row
++) {
1574 printf ("[ %f", view_matrix
[row
][0]);
1575 for (column
= 1; column
< 4; column
++) {
1576 printf (",\t%f", view_matrix
[row
][column
]);
1583 ghid_invalidate_all ();
1587 #define LEAD_USER_WIDTH 0.2 /* millimeters */
1588 #define LEAD_USER_PERIOD (1000 / 20) /* 20fps (in ms) */
1589 #define LEAD_USER_VELOCITY 3. /* millimeters per second */
1590 #define LEAD_USER_ARC_COUNT 3
1591 #define LEAD_USER_ARC_SEPARATION 3. /* millimeters */
1592 #define LEAD_USER_INITIAL_RADIUS 10. /* millimetres */
1593 #define LEAD_USER_COLOR_R 1.
1594 #define LEAD_USER_COLOR_G 1.
1595 #define LEAD_USER_COLOR_B 0.
1598 draw_lead_user (render_priv
*priv
)
1601 double radius
= priv
->lead_user_radius
;
1602 double width
= MM_TO_COORD (LEAD_USER_WIDTH
);
1603 double separation
= MM_TO_COORD (LEAD_USER_ARC_SEPARATION
);
1605 if (!priv
->lead_user
)
1608 glPushAttrib (GL_CURRENT_BIT
| GL_COLOR_BUFFER_BIT
);
1609 glEnable (GL_COLOR_LOGIC_OP
);
1611 glColor3f (LEAD_USER_COLOR_R
, LEAD_USER_COLOR_G
,LEAD_USER_COLOR_B
);
1614 /* arcs at the approrpriate radii */
1616 for (i
= 0; i
< LEAD_USER_ARC_COUNT
; i
++, radius
-= separation
)
1619 radius
+= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
1621 /* Draw an arc at radius */
1622 hidgl_draw_arc (width
, priv
->lead_user_x
, priv
->lead_user_y
,
1623 radius
, radius
, 0, 360, gport
->view
.coord_per_px
);
1626 hidgl_flush_triangles (&buffer
);
1631 lead_user_cb (gpointer data
)
1633 render_priv
*priv
= data
;
1635 double elapsed_time
;
1637 /* Queue a redraw */
1638 ghid_invalidate_all ();
1641 elapsed_time
= g_timer_elapsed (priv
->lead_user_timer
, NULL
);
1642 g_timer_start (priv
->lead_user_timer
);
1644 step
= MM_TO_COORD (LEAD_USER_VELOCITY
* elapsed_time
);
1645 if (priv
->lead_user_radius
> step
)
1646 priv
->lead_user_radius
-= step
;
1648 priv
->lead_user_radius
= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
1654 ghid_lead_user_to_location (Coord x
, Coord y
)
1656 render_priv
*priv
= gport
->render_priv
;
1658 ghid_cancel_lead_user ();
1660 priv
->lead_user
= true;
1661 priv
->lead_user_x
= x
;
1662 priv
->lead_user_y
= y
;
1663 priv
->lead_user_radius
= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
1664 priv
->lead_user_timeout
= g_timeout_add (LEAD_USER_PERIOD
, lead_user_cb
, priv
);
1665 priv
->lead_user_timer
= g_timer_new ();
1669 ghid_cancel_lead_user (void)
1671 render_priv
*priv
= gport
->render_priv
;
1673 if (priv
->lead_user_timeout
)
1674 g_source_remove (priv
->lead_user_timeout
);
1676 if (priv
->lead_user_timer
)
1677 g_timer_destroy (priv
->lead_user_timer
);
1679 if (priv
->lead_user
)
1680 ghid_invalidate_all ();
1682 priv
->lead_user_timeout
= 0;
1683 priv
->lead_user_timer
= NULL
;
1684 priv
->lead_user
= false;