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
;
38 extern HID_DRAW_CLASS ghid_graphics_class
;
40 static hidGC current_gc
= NULL
;
42 /* Sets gport->u_gc to the "right" GC to use (wrt mask or window)
44 #define USE_GC(gc) if (!use_gc(gc)) return
46 static enum mask_mode cur_mask
= HID_MASK_OFF
;
47 static GLfloat view_matrix
[4][4] = {{1.0, 0.0, 0.0, 0.0},
50 {0.0, 0.0, 0.0, 1.0}};
51 static GLfloat last_modelview_matrix
[4][4] = {{1.0, 0.0, 0.0, 0.0},
54 {0.0, 0.0, 0.0, 1.0}};
55 static int global_view_2d
= 1;
57 typedef struct render_priv
{
58 GdkGLConfig
*glconfig
;
61 int subcomposite_stencil_bit
;
62 char *current_colorname
;
63 double current_alpha_mult
;
64 GTimer
*time_since_expose
;
66 /* Feature for leading the user to a particular location */
67 guint lead_user_timeout
;
68 GTimer
*lead_user_timer
;
70 Coord lead_user_radius
;
77 typedef struct gtk_gc_struct
79 struct hid_gc_struct hid_gc
; /* Parent */
81 const char *colorname
;
87 static void draw_lead_user (render_priv
*priv
);
88 static void ghid_unproject_to_z_plane (int ex
, int ey
, Coord pcb_z
, Coord
*pcb_x
, Coord
*pcb_y
);
92 start_subcomposite (void)
94 render_priv
*priv
= gport
->render_priv
;
97 /* Flush out any existing geoemtry to be rendered */
98 hidgl_flush_triangles (&buffer
);
100 glEnable (GL_STENCIL_TEST
); /* Enable Stencil test */
101 glStencilOp (GL_KEEP
, GL_KEEP
, GL_REPLACE
); /* Stencil pass => replace stencil value (with 1) */
103 stencil_bit
= hidgl_assign_clear_stencil_bit(); /* Get a new (clean) bitplane to stencil with */
104 glStencilMask (stencil_bit
); /* Only write to our subcompositing stencil bitplane */
105 glStencilFunc (GL_GREATER
, stencil_bit
, stencil_bit
); /* Pass stencil test if our assigned bit is clear */
107 priv
->subcomposite_stencil_bit
= stencil_bit
;
111 end_subcomposite (void)
113 render_priv
*priv
= gport
->render_priv
;
115 /* Flush out any existing geoemtry to be rendered */
116 hidgl_flush_triangles (&buffer
);
118 hidgl_return_stencil_bit (priv
->subcomposite_stencil_bit
); /* Relinquish any bitplane we previously used */
121 glStencilFunc (GL_ALWAYS
, 0, 0); /* Always pass stencil test */
122 glDisable (GL_STENCIL_TEST
); /* Disable Stencil test */
124 priv
->subcomposite_stencil_bit
= 0;
129 ghid_set_layer (const char *name
, int group
, int empty
)
131 render_priv
*priv
= gport
->render_priv
;
133 if (idx
>= 0 && idx
< max_group
)
135 int n
= PCB
->LayerGroups
.Number
[group
];
136 for (idx
= 0; idx
< n
-1; idx
++)
138 int ni
= PCB
->LayerGroups
.Entries
[group
][idx
];
139 if (ni
>= 0 && ni
< max_copper_layer
+ 2
140 && PCB
->Data
->Layer
[ni
].On
)
143 idx
= PCB
->LayerGroups
.Entries
[group
][idx
];
147 start_subcomposite ();
149 if (idx
>= 0 && idx
< max_copper_layer
+ 2)
151 priv
->trans_lines
= true;
152 return PCB
->Data
->Layer
[idx
].On
;
156 switch (SL_TYPE (idx
))
159 return PCB
->InvisibleObjectsOn
;
162 return TEST_FLAG (SHOWMASKFLAG
, PCB
);
165 priv
->trans_lines
= true;
167 return PCB
->ElementOn
;
176 priv
->trans_lines
= true;
184 ghid_end_layer (void)
190 ghid_destroy_gc (hidGC gc
)
198 hidGC gc
= (hidGC
) g_new0 (struct gtk_gc_struct
, 1);
199 gtkGC gtk_gc
= (gtkGC
)gc
;
202 gc
->hid_draw
= &ghid_graphics
;
204 gtk_gc
->colorname
= Settings
.BackgroundColor
;
205 gtk_gc
->alpha_mult
= 1.0;
211 ghid_draw_grid (BoxType
*drawn_area
)
213 if (Vz (PCB
->Grid
) < MIN_GRID_DISTANCE
)
216 if (gdk_color_parse (Settings
.GridColor
, &gport
->grid_color
))
218 gport
->grid_color
.red
^= gport
->bg_color
.red
;
219 gport
->grid_color
.green
^= gport
->bg_color
.green
;
220 gport
->grid_color
.blue
^= gport
->bg_color
.blue
;
223 glEnable (GL_COLOR_LOGIC_OP
);
226 glColor3f (gport
->grid_color
.red
/ 65535.,
227 gport
->grid_color
.green
/ 65535.,
228 gport
->grid_color
.blue
/ 65535.);
230 hidgl_draw_grid (drawn_area
);
232 glDisable (GL_COLOR_LOGIC_OP
);
236 ghid_draw_bg_image (void)
238 static GLuint texture_handle
= 0;
240 if (!ghidgui
->bg_pixbuf
)
243 if (texture_handle
== 0)
245 int width
= gdk_pixbuf_get_width (ghidgui
->bg_pixbuf
);
246 int height
= gdk_pixbuf_get_height (ghidgui
->bg_pixbuf
);
247 int rowstride
= gdk_pixbuf_get_rowstride (ghidgui
->bg_pixbuf
);
248 int bits_per_sample
= gdk_pixbuf_get_bits_per_sample (ghidgui
->bg_pixbuf
);
249 int n_channels
= gdk_pixbuf_get_n_channels (ghidgui
->bg_pixbuf
);
250 unsigned char *pixels
= gdk_pixbuf_get_pixels (ghidgui
->bg_pixbuf
);
252 g_warn_if_fail (bits_per_sample
== 8);
253 g_warn_if_fail (rowstride
== width
* n_channels
);
255 glGenTextures (1, &texture_handle
);
256 glBindTexture (GL_TEXTURE_2D
, texture_handle
);
258 /* XXX: We should proabbly determine what the maxmimum texture supported is,
259 * and if our image is larger, shrink it down using GDK pixbuf routines
260 * rather than having it fail below.
263 glTexImage2D (GL_TEXTURE_2D
, 0, GL_RGB
, width
, height
, 0,
264 (n_channels
== 4) ? GL_RGBA
: GL_RGB
, GL_UNSIGNED_BYTE
, pixels
);
267 glBindTexture (GL_TEXTURE_2D
, texture_handle
);
269 glTexEnvf (GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_DECAL
);
270 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
271 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
272 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
273 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
274 glEnable (GL_TEXTURE_2D
);
276 /* Render a quad with the background as a texture */
279 glTexCoord2d (0., 0.);
280 glVertex3i (0, 0, 0);
281 glTexCoord2d (1., 0.);
282 glVertex3i (PCB
->MaxWidth
, 0, 0);
283 glTexCoord2d (1., 1.);
284 glVertex3i (PCB
->MaxWidth
, PCB
->MaxHeight
, 0);
285 glTexCoord2d (0., 1.);
286 glVertex3i (0, PCB
->MaxHeight
, 0);
289 glDisable (GL_TEXTURE_2D
);
293 ghid_use_mask (enum mask_mode mode
)
295 static int stencil_bit
= 0;
297 if (mode
== cur_mask
)
300 /* Flush out any existing geoemtry to be rendered */
301 hidgl_flush_triangles (&buffer
);
305 case HID_MASK_BEFORE
:
306 /* The HID asks not to receive this mask type, so warn if we get it */
307 g_return_if_reached ();
310 /* Write '1' to the stencil buffer where the solder-mask should not be drawn. */
311 glColorMask (0, 0, 0, 0); /* Disable writting in color buffer */
312 glEnable (GL_STENCIL_TEST
); /* Enable Stencil test */
313 stencil_bit
= hidgl_assign_clear_stencil_bit(); /* Get a new (clean) bitplane to stencil with */
314 glStencilFunc (GL_ALWAYS
, stencil_bit
, stencil_bit
); /* Always pass stencil test, write stencil_bit */
315 glStencilMask (stencil_bit
); /* Only write to our subcompositing stencil bitplane */
316 glStencilOp (GL_KEEP
, GL_KEEP
, GL_REPLACE
); /* Stencil pass => replace stencil value (with 1) */
320 /* Drawing operations as masked to areas where the stencil buffer is '0' */
321 glColorMask (1, 1, 1, 1); /* Enable drawing of r, g, b & a */
322 glStencilFunc (GL_GEQUAL
, 0, stencil_bit
); /* Draw only where our bit of the stencil buffer is clear */
323 glStencilOp (GL_KEEP
, GL_KEEP
, GL_KEEP
); /* Stencil buffer read only */
327 /* Disable stenciling */
328 hidgl_return_stencil_bit (stencil_bit
); /* Relinquish any bitplane we previously used */
329 glDisable (GL_STENCIL_TEST
); /* Disable Stencil test */
336 /* Config helper functions for when the user changes color preferences.
337 | set_special colors used in the gtkhid.
340 set_special_grid_color (void)
342 if (!gport
->colormap
)
344 gport
->grid_color
.red
^= gport
->bg_color
.red
;
345 gport
->grid_color
.green
^= gport
->bg_color
.green
;
346 gport
->grid_color
.blue
^= gport
->bg_color
.blue
;
350 ghid_set_special_colors (HID_Attribute
* ha
)
352 if (!ha
->name
|| !ha
->value
)
354 if (!strcmp (ha
->name
, "background-color"))
356 ghid_map_color_string (*(char **) ha
->value
, &gport
->bg_color
);
357 set_special_grid_color ();
359 else if (!strcmp (ha
->name
, "off-limit-color"))
361 ghid_map_color_string (*(char **) ha
->value
, &gport
->offlimits_color
);
363 else if (!strcmp (ha
->name
, "grid-color"))
365 ghid_map_color_string (*(char **) ha
->value
, &gport
->grid_color
);
366 set_special_grid_color ();
380 set_gl_color_for_gc (hidGC gc
)
382 gtkGC gtk_gc
= (gtkGC
)gc
;
383 render_priv
*priv
= gport
->render_priv
;
384 static void *cache
= NULL
;
389 if (priv
->current_colorname
!= NULL
&&
390 strcmp (priv
->current_colorname
, gtk_gc
->colorname
) == 0 &&
391 priv
->current_alpha_mult
== gtk_gc
->alpha_mult
)
394 free (priv
->current_colorname
);
395 priv
->current_colorname
= strdup (gtk_gc
->colorname
);
396 priv
->current_alpha_mult
= gtk_gc
->alpha_mult
;
398 if (gport
->colormap
== NULL
)
399 gport
->colormap
= gtk_widget_get_colormap (gport
->top_window
);
400 if (strcmp (gtk_gc
->colorname
, "erase") == 0)
402 r
= gport
->bg_color
.red
/ 65535.;
403 g
= gport
->bg_color
.green
/ 65535.;
404 b
= gport
->bg_color
.blue
/ 65535.;
407 else if (strcmp (gtk_gc
->colorname
, "drill") == 0)
409 r
= gport
->offlimits_color
.red
/ 65535.;
410 g
= gport
->offlimits_color
.green
/ 65535.;
411 b
= gport
->offlimits_color
.blue
/ 65535.;
416 if (hid_cache_color (0, gtk_gc
->colorname
, &cval
, &cache
))
417 cc
= (ColorCache
*) cval
.ptr
;
420 cc
= (ColorCache
*) malloc (sizeof (ColorCache
));
421 memset (cc
, 0, sizeof (*cc
));
423 hid_cache_color (1, gtk_gc
->colorname
, &cval
, &cache
);
428 if (gdk_color_parse (gtk_gc
->colorname
, &cc
->color
))
429 gdk_color_alloc (gport
->colormap
, &cc
->color
);
431 gdk_color_white (gport
->colormap
, &cc
->color
);
432 cc
->red
= cc
->color
.red
/ 65535.;
433 cc
->green
= cc
->color
.green
/ 65535.;
434 cc
->blue
= cc
->color
.blue
/ 65535.;
444 a
*= gtk_gc
->alpha_mult
;
445 if (!priv
->trans_lines
)
448 if (g
> maxi
) maxi
= g
;
449 if (b
> maxi
) maxi
= b
;
450 mult
= MIN (1 / a
, 1 / maxi
);
458 if(!priv
->in_context
)
461 hidgl_flush_triangles (&buffer
);
462 glColor4d (r
, g
, b
, a
);
466 ghid_set_color (hidGC gc
, const char *name
)
468 gtkGC gtk_gc
= (gtkGC
)gc
;
470 gtk_gc
->colorname
= name
;
471 set_gl_color_for_gc (gc
);
475 ghid_set_alpha_mult (hidGC gc
, double alpha_mult
)
477 gtkGC gtk_gc
= (gtkGC
)gc
;
479 gtk_gc
->alpha_mult
= alpha_mult
;
480 set_gl_color_for_gc (gc
);
484 ghid_set_line_cap (hidGC gc
, EndCapStyle style
)
486 gtkGC gtk_gc
= (gtkGC
)gc
;
492 ghid_set_line_width (hidGC gc
, Coord width
)
494 gtkGC gtk_gc
= (gtkGC
)gc
;
496 gtk_gc
->width
= width
;
501 ghid_set_draw_xor (hidGC gc
, int xor)
503 /* NOT IMPLEMENTED */
505 /* Only presently called when setting up a crosshair GC.
506 * We manage our own drawing model for that anyway. */
510 ghid_set_draw_faded (hidGC gc
, int faded
)
512 printf ("ghid_set_draw_faded(%p,%d) -- not implemented\n", gc
, faded
);
516 ghid_set_line_cap_angle (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
518 printf ("ghid_set_line_cap_angle() -- not implemented\n");
522 ghid_invalidate_current_gc (void)
530 if (gc
->hid
!= &ghid_hid
)
532 fprintf (stderr
, "Fatal: GC from another HID passed to GTK HID\n");
536 if (current_gc
== gc
)
541 set_gl_color_for_gc (gc
);
546 ghid_draw_line (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
548 gtkGC gtk_gc
= (gtkGC
)gc
;
551 hidgl_draw_line (gtk_gc
->cap
, gtk_gc
->width
, x1
, y1
, x2
, y2
, gport
->view
.coord_per_px
);
555 ghid_draw_arc (hidGC gc
, Coord cx
, Coord cy
, Coord xradius
, Coord yradius
,
556 Angle start_angle
, Angle delta_angle
)
558 gtkGC gtk_gc
= (gtkGC
)gc
;
561 hidgl_draw_arc (gtk_gc
->width
, cx
, cy
, xradius
, yradius
,
562 start_angle
, delta_angle
, gport
->view
.coord_per_px
);
566 ghid_draw_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
570 hidgl_draw_rect (x1
, y1
, x2
, y2
);
575 ghid_fill_circle (hidGC gc
, Coord cx
, Coord cy
, Coord radius
)
579 hidgl_fill_circle (cx
, cy
, radius
, gport
->view
.coord_per_px
);
584 ghid_fill_polygon (hidGC gc
, int n_coords
, Coord
*x
, Coord
*y
)
588 hidgl_fill_polygon (n_coords
, x
, y
);
592 ghid_fill_pcb_polygon (hidGC gc
, PolygonType
*poly
, const BoxType
*clip_box
)
596 hidgl_fill_pcb_polygon (poly
, clip_box
, gport
->view
.coord_per_px
);
600 ghid_thindraw_pcb_polygon (hidGC gc
, PolygonType
*poly
, const BoxType
*clip_box
)
602 common_thindraw_pcb_polygon (gc
, poly
, clip_box
);
603 ghid_set_alpha_mult (gc
, 0.25);
604 hid_draw_fill_pcb_polygon (gc
, poly
, clip_box
);
605 ghid_set_alpha_mult (gc
, 1.0);
609 ghid_fill_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
613 hidgl_fill_rect (x1
, y1
, x2
, y2
);
617 ghid_invalidate_lr (int left
, int right
, int top
, int bottom
)
619 ghid_invalidate_all ();
622 #define MAX_ELAPSED (50. / 1000.) /* 50ms */
624 ghid_invalidate_all ()
626 render_priv
*priv
= gport
->render_priv
;
627 double elapsed
= g_timer_elapsed (priv
->time_since_expose
, NULL
);
629 ghid_draw_area_update (gport
, NULL
);
631 if (elapsed
> MAX_ELAPSED
)
632 gdk_window_process_all_updates ();
636 ghid_notify_crosshair_change (bool changes_complete
)
638 /* We sometimes get called before the GUI is up */
639 if (gport
->drawing_area
== NULL
)
642 /* FIXME: We could just invalidate the bounds of the crosshair attached objects? */
643 ghid_invalidate_all ();
647 ghid_notify_mark_change (bool changes_complete
)
649 /* We sometimes get called before the GUI is up */
650 if (gport
->drawing_area
== NULL
)
653 /* FIXME: We could just invalidate the bounds of the mark? */
654 ghid_invalidate_all ();
658 draw_right_cross (gint x
, gint y
, gint z
)
660 glVertex3i (x
, 0, z
);
661 glVertex3i (x
, PCB
->MaxHeight
, z
);
662 glVertex3i (0, y
, z
);
663 glVertex3i (PCB
->MaxWidth
, y
, z
);
667 draw_slanted_cross (gint x
, gint y
, gint z
)
671 x0
= x
+ (PCB
->MaxHeight
- y
);
672 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
674 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
675 y0
= y
+ (PCB
->MaxWidth
- x
);
676 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
678 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
679 glVertex3i (x0
, y0
, z
);
680 glVertex3i (x1
, y1
, z
);
682 x0
= x
- (PCB
->MaxHeight
- y
);
683 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
685 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
687 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
688 y1
= y
- (PCB
->MaxWidth
- x
);
689 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
690 glVertex3i (x0
, y0
, z
);
691 glVertex3i (x1
, y1
, z
);
695 draw_dozen_cross (gint x
, gint y
, gint z
)
698 gdouble tan60
= sqrt (3);
700 x0
= x
+ (PCB
->MaxHeight
- y
) / tan60
;
701 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
703 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
704 y0
= y
+ (PCB
->MaxWidth
- x
) * tan60
;
705 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
707 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
708 glVertex3i (x0
, y0
, z
);
709 glVertex3i (x1
, y1
, z
);
711 x0
= x
+ (PCB
->MaxHeight
- y
) * tan60
;
712 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
714 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
715 y0
= y
+ (PCB
->MaxWidth
- x
) / tan60
;
716 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
718 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
719 glVertex3i (x0
, y0
, z
);
720 glVertex3i (x1
, y1
, z
);
722 x0
= x
- (PCB
->MaxHeight
- y
) / tan60
;
723 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
725 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
727 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
728 y1
= y
- (PCB
->MaxWidth
- x
) * tan60
;
729 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
730 glVertex3i (x0
, y0
, z
);
731 glVertex3i (x1
, y1
, z
);
733 x0
= x
- (PCB
->MaxHeight
- y
) * tan60
;
734 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
736 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
738 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
739 y1
= y
- (PCB
->MaxWidth
- x
) / tan60
;
740 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
741 glVertex3i (x0
, y0
, z
);
742 glVertex3i (x1
, y1
, z
);
746 draw_crosshair (render_priv
*priv
)
749 static int done_once
= 0;
750 static GdkColor cross_color
;
755 /* FIXME: when CrossColor changed from config */
756 ghid_map_color_string (Settings
.CrossColor
, &cross_color
);
759 x
= gport
->crosshair_x
;
760 y
= gport
->crosshair_y
;
763 glEnable (GL_COLOR_LOGIC_OP
);
766 glColor3f (cross_color
.red
/ 65535.,
767 cross_color
.green
/ 65535.,
768 cross_color
.blue
/ 65535.);
772 draw_right_cross (x
, y
, z
);
773 if (Crosshair
.shape
== Union_Jack_Crosshair_Shape
)
774 draw_slanted_cross (x
, y
, z
);
775 if (Crosshair
.shape
== Dozen_Crosshair_Shape
)
776 draw_dozen_cross (x
, y
, z
);
780 glDisable (GL_COLOR_LOGIC_OP
);
784 ghid_init_renderer (int *argc
, char ***argv
, GHidPort
*port
)
788 port
->render_priv
= priv
= g_new0 (render_priv
, 1);
789 port
->render_priv
->crosshair_gc
= hid_draw_make_gc (&ghid_graphics
);
791 priv
->time_since_expose
= g_timer_new ();
793 gtk_gl_init(argc
, argv
);
795 /* setup GL-context */
796 priv
->glconfig
= gdk_gl_config_new_by_mode (GDK_GL_MODE_RGBA
|
797 GDK_GL_MODE_STENCIL
|
801 printf ("Could not setup GL-context!\n");
802 return; /* Should we abort? */
805 /* Setup HID function pointers specific to the GL renderer*/
806 ghid_graphics_class
.end_layer
= ghid_end_layer
;
807 ghid_graphics_class
.fill_pcb_polygon
= ghid_fill_pcb_polygon
;
808 ghid_graphics_class
.thindraw_pcb_polygon
= ghid_thindraw_pcb_polygon
;
812 ghid_shutdown_renderer (GHidPort
*port
)
814 render_priv
*priv
= port
->render_priv
;
816 hid_draw_destroy_gc (priv
->crosshair_gc
);
817 ghid_cancel_lead_user ();
818 g_free (port
->render_priv
);
819 port
->render_priv
= NULL
;
823 ghid_init_drawing_widget (GtkWidget
*widget
, GHidPort
*port
)
825 render_priv
*priv
= port
->render_priv
;
827 gtk_widget_set_gl_capability (widget
,
835 ghid_drawing_area_configure_hook (GHidPort
*port
)
840 ghid_start_drawing (GHidPort
*port
, GtkWidget
*widget
)
842 GdkGLContext
*pGlContext
= gtk_widget_get_gl_context (widget
);
843 GdkGLDrawable
*pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
845 /* make GL-context "current" */
846 if (!gdk_gl_drawable_gl_begin (pGlDrawable
, pGlContext
))
849 port
->render_priv
->in_context
= true;
855 ghid_end_drawing (GHidPort
*port
, GtkWidget
*widget
)
857 GdkGLDrawable
*pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
859 if (gdk_gl_drawable_is_double_buffered (pGlDrawable
))
860 gdk_gl_drawable_swap_buffers (pGlDrawable
);
864 port
->render_priv
->in_context
= false;
866 /* end drawing to current GL-context */
867 gdk_gl_drawable_gl_end (pGlDrawable
);
871 ghid_screen_update (void)
877 ghid_drawing_area_expose_cb (GtkWidget
*widget
,
881 render_priv
*priv
= port
->render_priv
;
882 GtkAllocation allocation
;
890 gtk_widget_get_allocation (widget
, &allocation
);
892 ghid_start_drawing (port
, widget
);
893 hidgl_start_render ();
895 /* If we don't have any stencil bits available,
896 we can't use the hidgl polygon drawing routine */
897 /* TODO: We could use the GLU tessellator though */
898 if (hidgl_stencil_bits() == 0)
899 ghid_graphics_class
.fill_pcb_polygon
= common_fill_pcb_polygon
;
902 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
904 glViewport (0, 0, allocation
.width
, allocation
.height
);
906 glEnable (GL_SCISSOR_TEST
);
907 glScissor (ev
->area
.x
,
908 allocation
.height
- ev
->area
.height
- ev
->area
.y
,
909 ev
->area
.width
, ev
->area
.height
);
911 glMatrixMode (GL_PROJECTION
);
913 glOrtho (0, allocation
.width
, allocation
.height
, 0, -100000, 100000);
914 glMatrixMode (GL_MODELVIEW
);
916 glTranslatef (widget
->allocation
.width
/ 2., widget
->allocation
.height
/ 2., 0);
917 glMultMatrixf ((GLfloat
*)view_matrix
);
918 glTranslatef (-widget
->allocation
.width
/ 2., -widget
->allocation
.height
/ 2., 0);
919 glScalef ((port
->view
.flip_x
? -1. : 1.) / port
->view
.coord_per_px
,
920 (port
->view
.flip_y
? -1. : 1.) / port
->view
.coord_per_px
,
921 ((port
->view
.flip_x
== port
->view
.flip_y
) ? 1. : -1.) / port
->view
.coord_per_px
);
922 glTranslatef (port
->view
.flip_x
? port
->view
.x0
- PCB
->MaxWidth
:
924 port
->view
.flip_y
? port
->view
.y0
- PCB
->MaxHeight
:
926 glGetFloatv (GL_MODELVIEW_MATRIX
, (GLfloat
*)last_modelview_matrix
);
928 glEnable (GL_STENCIL_TEST
);
929 glClearColor (port
->offlimits_color
.red
/ 65535.,
930 port
->offlimits_color
.green
/ 65535.,
931 port
->offlimits_color
.blue
/ 65535.,
935 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
936 hidgl_reset_stencil_usage ();
938 /* Disable the stencil test until we need it - otherwise it gets dirty */
939 glDisable (GL_STENCIL_TEST
);
941 glStencilFunc (GL_ALWAYS
, 0, 0);
943 /* Test the 8 corners of a cube spanning the event */
944 min_depth
= -50; /* FIXME */
945 max_depth
= 0; /* FIXME */
947 ghid_unproject_to_z_plane (ev
->area
.x
,
949 min_depth
, &new_x
, &new_y
);
950 max_x
= min_x
= new_x
;
951 max_y
= min_y
= new_y
;
953 ghid_unproject_to_z_plane (ev
->area
.x
,
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
,
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
, ev
->area
.y
,
967 max_depth
, &new_x
, &new_y
);
968 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
969 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
972 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
,
973 ev
->area
.y
+ ev
->area
.height
,
974 min_depth
, &new_x
, &new_y
);
975 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
976 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
978 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
,
979 ev
->area
.y
+ ev
->area
.height
,
980 max_depth
, &new_x
, &new_y
);
981 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
982 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
985 ghid_unproject_to_z_plane (ev
->area
.x
,
986 ev
->area
.y
+ ev
->area
.height
,
989 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
990 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
992 ghid_unproject_to_z_plane (ev
->area
.x
,
993 ev
->area
.y
+ ev
->area
.height
,
996 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
997 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
999 region
.X1
= min_x
; region
.X2
= max_x
+ 1;
1000 region
.Y1
= min_y
; region
.Y2
= max_y
+ 1;
1002 region
.X1
= MAX (0, MIN (PCB
->MaxWidth
, region
.X1
));
1003 region
.X2
= MAX (0, MIN (PCB
->MaxWidth
, region
.X2
));
1004 region
.Y1
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y1
));
1005 region
.Y2
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y2
));
1007 glColor3f (port
->bg_color
.red
/ 65535.,
1008 port
->bg_color
.green
/ 65535.,
1009 port
->bg_color
.blue
/ 65535.);
1012 glVertex3i (0, 0, -50);
1013 glVertex3i (PCB
->MaxWidth
, 0, -50);
1014 glVertex3i (PCB
->MaxWidth
, PCB
->MaxHeight
, -50);
1015 glVertex3i (0, PCB
->MaxHeight
, -50);
1018 ghid_draw_bg_image ();
1020 ghid_invalidate_current_gc ();
1021 hid_expose_callback (&ghid_hid
, ®ion
, 0);
1022 hidgl_flush_triangles (&buffer
);
1024 ghid_draw_grid (®ion
);
1026 ghid_invalidate_current_gc ();
1028 DrawAttached (priv
->crosshair_gc
);
1029 DrawMark (priv
->crosshair_gc
);
1030 hidgl_flush_triangles (&buffer
);
1032 draw_crosshair (priv
);
1033 hidgl_flush_triangles (&buffer
);
1035 draw_lead_user (priv
);
1037 hidgl_finish_render ();
1038 ghid_end_drawing (port
, widget
);
1040 g_timer_start (priv
->time_since_expose
);
1045 /* This realize callback is used to work around a crash bug in some mesa
1046 * versions (observed on a machine running the intel i965 driver. It isn't
1047 * obvious why it helps, but somehow fiddling with the GL context here solves
1048 * the issue. The problem appears to have been fixed in recent mesa versions.
1051 ghid_port_drawing_realize_cb (GtkWidget
*widget
, gpointer data
)
1053 GdkGLContext
*glcontext
= gtk_widget_get_gl_context (widget
);
1054 GdkGLDrawable
*gldrawable
= gtk_widget_get_gl_drawable (widget
);
1056 if (!gdk_gl_drawable_gl_begin (gldrawable
, glcontext
))
1059 gdk_gl_drawable_gl_end (gldrawable
);
1064 ghid_pinout_preview_expose (GtkWidget
*widget
,
1067 GhidPinoutPreview
*pinout
= GHID_PINOUT_PREVIEW (widget
);
1068 GtkAllocation allocation
;
1069 view_data save_view
;
1070 int save_width
, save_height
;
1071 Coord save_max_width
;
1072 Coord save_max_height
;
1075 save_view
= gport
->view
;
1076 save_width
= gport
->width
;
1077 save_height
= gport
->height
;
1078 save_max_width
= PCB
->MaxWidth
;
1079 save_max_height
= PCB
->MaxHeight
;
1081 /* Setup zoom factor for drawing routines */
1083 gtk_widget_get_allocation (widget
, &allocation
);
1084 xz
= (double) pinout
->x_max
/ allocation
.width
;
1085 yz
= (double) pinout
->y_max
/ allocation
.height
;
1087 gport
->view
.coord_per_px
= xz
;
1089 gport
->view
.coord_per_px
= yz
;
1091 gport
->width
= allocation
.width
;
1092 gport
->height
= allocation
.height
;
1093 gport
->view
.width
= allocation
.width
* gport
->view
.coord_per_px
;
1094 gport
->view
.height
= allocation
.height
* gport
->view
.coord_per_px
;
1095 gport
->view
.x0
= (pinout
->x_max
- gport
->view
.width
) / 2;
1096 gport
->view
.y0
= (pinout
->y_max
- gport
->view
.height
) / 2;
1097 PCB
->MaxWidth
= pinout
->x_max
;
1098 PCB
->MaxHeight
= pinout
->y_max
;
1100 ghid_start_drawing (gport
, widget
);
1101 hidgl_start_render ();
1103 #if 0 /* We disable alpha blending here, as hid_expose_callback() does not
1104 * call set_layer() as appropriate for us to sub-composite rendering
1105 * from each layer when drawing a single element. If we leave alpha-
1106 * blending on, it means text and overlapping pads are rendered ugly.
1109 glEnable (GL_BLEND
);
1110 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1113 glViewport (0, 0, allocation
.width
, allocation
.height
);
1115 #if 0 /* We disable the scissor test here, as it is interacting badly with
1116 * being handed expose events which don't cover the whole window.
1117 * As we have a double-buffered GL window, we end up with unintialised
1118 * contents remaining in the unpainted areas (outside the scissor
1119 * region), and these are being flipped onto the screen.
1121 * The debugging code below shows multiple expose events when the
1122 * window is shown the first time, some of which are very small.
1124 * XXX: There is clearly a perforamnce issue here, in that we may
1125 * be rendering the preview more times, and over a larger area
1126 * than is really required.
1129 glEnable (GL_SCISSOR_TEST
);
1130 glScissor (ev
->area
.x
,
1131 allocation
.height
- ev
->area
.height
- ev
->area
.y
,
1132 ev
->area
.width
, ev
->area
.height
);
1136 printf ("EVT: %i, %i, w=%i, h=%i, Scissor setup: glScissor (%f, %f, %f, %f);\n",
1137 ev
->area
.x
, ev
->area
.y
, ev
->area
.width
, ev
->area
.height
,
1139 (double)(allocation
.height
- ev
->area
.height
- ev
->area
.y
),
1140 (double)ev
->area
.width
,
1141 (double)ev
->area
.height
);
1144 glMatrixMode (GL_PROJECTION
);
1146 glOrtho (0, allocation
.width
, allocation
.height
, 0, -100000, 100000);
1147 glMatrixMode (GL_MODELVIEW
);
1149 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
1151 glClearColor (gport
->bg_color
.red
/ 65535.,
1152 gport
->bg_color
.green
/ 65535.,
1153 gport
->bg_color
.blue
/ 65535.,
1157 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
1158 hidgl_reset_stencil_usage ();
1160 /* Disable the stencil test until we need it - otherwise it gets dirty */
1161 glDisable (GL_STENCIL_TEST
);
1163 glStencilFunc (GL_ALWAYS
, 0, 0);
1165 /* call the drawing routine */
1166 ghid_invalidate_current_gc ();
1168 glScalef ((gport
->view
.flip_x
? -1. : 1.) / gport
->view
.coord_per_px
,
1169 (gport
->view
.flip_y
? -1. : 1.) / gport
->view
.coord_per_px
,
1170 ((gport
->view
.flip_x
== gport
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
1171 glTranslatef (gport
->view
.flip_x
? gport
->view
.x0
- PCB
->MaxWidth
:
1173 gport
->view
.flip_y
? gport
->view
.y0
- PCB
->MaxHeight
:
1174 -gport
->view
.y0
, 0);
1176 hid_expose_callback (&ghid_hid
, NULL
, pinout
->element
);
1177 hidgl_flush_triangles (&buffer
);
1180 hidgl_finish_render ();
1181 ghid_end_drawing (gport
, widget
);
1183 gport
->view
= save_view
;
1184 gport
->width
= save_width
;
1185 gport
->height
= save_height
;
1186 PCB
->MaxWidth
= save_max_width
;
1187 PCB
->MaxHeight
= save_max_height
;
1194 ghid_render_pixmap (int cx
, int cy
, double zoom
, int width
, int height
, int depth
)
1196 GdkGLConfig
*glconfig
;
1198 GdkGLPixmap
*glpixmap
;
1199 GdkGLContext
* glcontext
;
1200 GdkGLDrawable
* gldrawable
;
1201 view_data save_view
;
1202 int save_width
, save_height
;
1205 save_view
= gport
->view
;
1206 save_width
= gport
->width
;
1207 save_height
= gport
->height
;
1209 /* Setup rendering context for drawing routines
1212 glconfig
= gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB
|
1213 GDK_GL_MODE_STENCIL
|
1214 GDK_GL_MODE_SINGLE
);
1216 pixmap
= gdk_pixmap_new (NULL
, width
, height
, depth
);
1217 glpixmap
= gdk_pixmap_set_gl_capability (pixmap
, glconfig
, NULL
);
1218 gldrawable
= GDK_GL_DRAWABLE (glpixmap
);
1219 glcontext
= gdk_gl_context_new (gldrawable
, NULL
, TRUE
, GDK_GL_RGBA_TYPE
);
1221 /* Setup zoom factor for drawing routines */
1223 gport
->view
.coord_per_px
= zoom
;
1224 gport
->width
= width
;
1225 gport
->height
= height
;
1226 gport
->view
.width
= width
* gport
->view
.coord_per_px
;
1227 gport
->view
.height
= height
* gport
->view
.coord_per_px
;
1228 gport
->view
.x0
= gport
->view
.flip_x
? PCB
->MaxWidth
- cx
: cx
;
1229 gport
->view
.x0
-= gport
->view
.height
/ 2;
1230 gport
->view
.y0
= gport
->view
.flip_y
? PCB
->MaxHeight
- cy
: cy
;
1231 gport
->view
.y0
-= gport
->view
.width
/ 2;
1233 /* make GL-context "current" */
1234 if (!gdk_gl_drawable_gl_begin (gldrawable
, glcontext
)) {
1237 hidgl_start_render ();
1238 gport
->render_priv
->in_context
= true;
1240 glEnable (GL_BLEND
);
1241 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1243 glViewport (0, 0, width
, height
);
1245 glEnable (GL_SCISSOR_TEST
);
1246 glScissor (0, 0, width
, height
);
1248 glMatrixMode (GL_PROJECTION
);
1250 glOrtho (0, width
, height
, 0, -100000, 100000);
1251 glMatrixMode (GL_MODELVIEW
);
1253 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
1255 glClearColor (gport
->bg_color
.red
/ 65535.,
1256 gport
->bg_color
.green
/ 65535.,
1257 gport
->bg_color
.blue
/ 65535.,
1261 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
1262 hidgl_reset_stencil_usage ();
1264 /* Disable the stencil test until we need it - otherwise it gets dirty */
1265 glDisable (GL_STENCIL_TEST
);
1267 glStencilFunc (GL_ALWAYS
, 0, 0);
1269 /* call the drawing routine */
1270 ghid_invalidate_current_gc ();
1272 glScalef ((gport
->view
.flip_x
? -1. : 1.) / gport
->view
.coord_per_px
,
1273 (gport
->view
.flip_y
? -1. : 1.) / gport
->view
.coord_per_px
,
1274 ((gport
->view
.flip_x
== gport
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
1275 glTranslatef (gport
->view
.flip_x
? gport
->view
.x0
- PCB
->MaxWidth
:
1277 gport
->view
.flip_y
? gport
->view
.y0
- PCB
->MaxHeight
:
1278 -gport
->view
.y0
, 0);
1280 region
.X1
= MIN(Px(0), Px(gport
->width
+ 1));
1281 region
.Y1
= MIN(Py(0), Py(gport
->height
+ 1));
1282 region
.X2
= MAX(Px(0), Px(gport
->width
+ 1));
1283 region
.Y2
= MAX(Py(0), Py(gport
->height
+ 1));
1285 region
.X1
= MAX (0, MIN (PCB
->MaxWidth
, region
.X1
));
1286 region
.X2
= MAX (0, MIN (PCB
->MaxWidth
, region
.X2
));
1287 region
.Y1
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y1
));
1288 region
.Y2
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y2
));
1290 hid_expose_callback (&ghid_hid
, ®ion
, NULL
);
1291 hidgl_flush_triangles (&buffer
);
1296 hidgl_finish_render ();
1298 /* end drawing to current GL-context */
1299 gport
->render_priv
->in_context
= false;
1300 gdk_gl_drawable_gl_end (gldrawable
);
1302 gdk_pixmap_unset_gl_capability (pixmap
);
1304 g_object_unref (glconfig
);
1305 g_object_unref (glcontext
);
1307 gport
->view
= save_view
;
1308 gport
->width
= save_width
;
1309 gport
->height
= save_height
;
1315 ghid_request_debug_draw (void)
1317 GHidPort
*port
= gport
;
1318 GtkWidget
*widget
= port
->drawing_area
;
1319 GtkAllocation allocation
;
1321 gtk_widget_get_allocation (widget
, &allocation
);
1323 ghid_start_drawing (port
, widget
);
1324 hidgl_start_render ();
1326 glViewport (0, 0, allocation
.width
, allocation
.height
);
1328 glMatrixMode (GL_PROJECTION
);
1330 glOrtho (0, allocation
.width
, allocation
.height
, 0, 0, 100);
1331 glMatrixMode (GL_MODELVIEW
);
1333 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
1335 ghid_invalidate_current_gc ();
1337 /* Setup stenciling */
1338 glDisable (GL_STENCIL_TEST
);
1341 glScalef ((port
->view
.flip_x
? -1. : 1.) / port
->view
.coord_per_px
,
1342 (port
->view
.flip_y
? -1. : 1.) / port
->view
.coord_per_px
,
1343 ((gport
->view
.flip_x
== port
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
1344 glTranslatef (port
->view
.flip_x
? port
->view
.x0
- PCB
->MaxWidth
:
1346 port
->view
.flip_y
? port
->view
.y0
- PCB
->MaxHeight
:
1349 return ghid_hid
.graphics
;
1353 ghid_flush_debug_draw (void)
1355 GtkWidget
*widget
= gport
->drawing_area
;
1356 GdkGLDrawable
*pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
1358 hidgl_flush_triangles (&buffer
);
1360 if (gdk_gl_drawable_is_double_buffered (pGlDrawable
))
1361 gdk_gl_drawable_swap_buffers (pGlDrawable
);
1367 ghid_finish_debug_draw (void)
1369 hidgl_flush_triangles (&buffer
);
1372 hidgl_finish_render ();
1373 ghid_end_drawing (gport
, gport
->drawing_area
);
1377 determinant_2x2 (float m
[2][2])
1380 det
= m
[0][0] * m
[1][1] -
1387 determinant_4x4 (float m
[4][4])
1390 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] -
1391 m
[0][3] * m
[1][1] * m
[2][2] * m
[3][0]+m
[0][1] * m
[1][3] * m
[2][2] * m
[3][0] +
1392 m
[0][2] * m
[1][1] * m
[2][3] * m
[3][0]-m
[0][1] * m
[1][2] * m
[2][3] * m
[3][0] -
1393 m
[0][3] * m
[1][2] * m
[2][0] * m
[3][1]+m
[0][2] * m
[1][3] * m
[2][0] * m
[3][1] +
1394 m
[0][3] * m
[1][0] * m
[2][2] * m
[3][1]-m
[0][0] * m
[1][3] * m
[2][2] * m
[3][1] -
1395 m
[0][2] * m
[1][0] * m
[2][3] * m
[3][1]+m
[0][0] * m
[1][2] * m
[2][3] * m
[3][1] +
1396 m
[0][3] * m
[1][1] * m
[2][0] * m
[3][2]-m
[0][1] * m
[1][3] * m
[2][0] * m
[3][2] -
1397 m
[0][3] * m
[1][0] * m
[2][1] * m
[3][2]+m
[0][0] * m
[1][3] * m
[2][1] * m
[3][2] +
1398 m
[0][1] * m
[1][0] * m
[2][3] * m
[3][2]-m
[0][0] * m
[1][1] * m
[2][3] * m
[3][2] -
1399 m
[0][2] * m
[1][1] * m
[2][0] * m
[3][3]+m
[0][1] * m
[1][2] * m
[2][0] * m
[3][3] +
1400 m
[0][2] * m
[1][0] * m
[2][1] * m
[3][3]-m
[0][0] * m
[1][2] * m
[2][1] * m
[3][3] -
1401 m
[0][1] * m
[1][0] * m
[2][2] * m
[3][3]+m
[0][0] * m
[1][1] * m
[2][2] * m
[3][3];
1407 invert_2x2 (float m
[2][2], float out
[2][2])
1409 float scale
= 1 / determinant_2x2 (m
);
1410 out
[0][0] = m
[1][1] * scale
;
1411 out
[0][1] = -m
[0][1] * scale
;
1412 out
[1][0] = -m
[1][0] * scale
;
1413 out
[1][1] = m
[0][0] * scale
;
1418 invert_4x4 (float m
[4][4], float out
[4][4])
1420 float scale
= 1 / determinant_4x4 (m
);
1422 out
[0][0] = (m
[1][2] * m
[2][3] * m
[3][1] - m
[1][3] * m
[2][2] * m
[3][1] +
1423 m
[1][3] * m
[2][1] * m
[3][2] - m
[1][1] * m
[2][3] * m
[3][2] -
1424 m
[1][2] * m
[2][1] * m
[3][3] + m
[1][1] * m
[2][2] * m
[3][3]) * scale
;
1425 out
[0][1] = (m
[0][3] * m
[2][2] * m
[3][1] - m
[0][2] * m
[2][3] * m
[3][1] -
1426 m
[0][3] * m
[2][1] * m
[3][2] + m
[0][1] * m
[2][3] * m
[3][2] +
1427 m
[0][2] * m
[2][1] * m
[3][3] - m
[0][1] * m
[2][2] * m
[3][3]) * scale
;
1428 out
[0][2] = (m
[0][2] * m
[1][3] * m
[3][1] - m
[0][3] * m
[1][2] * m
[3][1] +
1429 m
[0][3] * m
[1][1] * m
[3][2] - m
[0][1] * m
[1][3] * m
[3][2] -
1430 m
[0][2] * m
[1][1] * m
[3][3] + m
[0][1] * m
[1][2] * m
[3][3]) * scale
;
1431 out
[0][3] = (m
[0][3] * m
[1][2] * m
[2][1] - m
[0][2] * m
[1][3] * m
[2][1] -
1432 m
[0][3] * m
[1][1] * m
[2][2] + m
[0][1] * m
[1][3] * m
[2][2] +
1433 m
[0][2] * m
[1][1] * m
[2][3] - m
[0][1] * m
[1][2] * m
[2][3]) * scale
;
1434 out
[1][0] = (m
[1][3] * m
[2][2] * m
[3][0] - m
[1][2] * m
[2][3] * m
[3][0] -
1435 m
[1][3] * m
[2][0] * m
[3][2] + m
[1][0] * m
[2][3] * m
[3][2] +
1436 m
[1][2] * m
[2][0] * m
[3][3] - m
[1][0] * m
[2][2] * m
[3][3]) * scale
;
1437 out
[1][1] = (m
[0][2] * m
[2][3] * m
[3][0] - m
[0][3] * m
[2][2] * m
[3][0] +
1438 m
[0][3] * m
[2][0] * m
[3][2] - m
[0][0] * m
[2][3] * m
[3][2] -
1439 m
[0][2] * m
[2][0] * m
[3][3] + m
[0][0] * m
[2][2] * m
[3][3]) * scale
;
1440 out
[1][2] = (m
[0][3] * m
[1][2] * m
[3][0] - m
[0][2] * m
[1][3] * m
[3][0] -
1441 m
[0][3] * m
[1][0] * m
[3][2] + m
[0][0] * m
[1][3] * m
[3][2] +
1442 m
[0][2] * m
[1][0] * m
[3][3] - m
[0][0] * m
[1][2] * m
[3][3]) * scale
;
1443 out
[1][3] = (m
[0][2] * m
[1][3] * m
[2][0] - m
[0][3] * m
[1][2] * m
[2][0] +
1444 m
[0][3] * m
[1][0] * m
[2][2] - m
[0][0] * m
[1][3] * m
[2][2] -
1445 m
[0][2] * m
[1][0] * m
[2][3] + m
[0][0] * m
[1][2] * m
[2][3]) * scale
;
1446 out
[2][0] = (m
[1][1] * m
[2][3] * m
[3][0] - m
[1][3] * m
[2][1] * m
[3][0] +
1447 m
[1][3] * m
[2][0] * m
[3][1] - m
[1][0] * m
[2][3] * m
[3][1] -
1448 m
[1][1] * m
[2][0] * m
[3][3] + m
[1][0] * m
[2][1] * m
[3][3]) * scale
;
1449 out
[2][1] = (m
[0][3] * m
[2][1] * m
[3][0] - m
[0][1] * m
[2][3] * m
[3][0] -
1450 m
[0][3] * m
[2][0] * m
[3][1] + m
[0][0] * m
[2][3] * m
[3][1] +
1451 m
[0][1] * m
[2][0] * m
[3][3] - m
[0][0] * m
[2][1] * m
[3][3]) * scale
;
1452 out
[2][2] = (m
[0][1] * m
[1][3] * m
[3][0] - m
[0][3] * m
[1][1] * m
[3][0] +
1453 m
[0][3] * m
[1][0] * m
[3][1] - m
[0][0] * m
[1][3] * m
[3][1] -
1454 m
[0][1] * m
[1][0] * m
[3][3] + m
[0][0] * m
[1][1] * m
[3][3]) * scale
;
1455 out
[2][3] = (m
[0][3] * m
[1][1] * m
[2][0] - m
[0][1] * m
[1][3] * m
[2][0] -
1456 m
[0][3] * m
[1][0] * m
[2][1] + m
[0][0] * m
[1][3] * m
[2][1] +
1457 m
[0][1] * m
[1][0] * m
[2][3] - m
[0][0] * m
[1][1] * m
[2][3]) * scale
;
1458 out
[3][0] = (m
[1][2] * m
[2][1] * m
[3][0] - m
[1][1] * m
[2][2] * m
[3][0] -
1459 m
[1][2] * m
[2][0] * m
[3][1] + m
[1][0] * m
[2][2] * m
[3][1] +
1460 m
[1][1] * m
[2][0] * m
[3][2] - m
[1][0] * m
[2][1] * m
[3][2]) * scale
;
1461 out
[3][1] = (m
[0][1] * m
[2][2] * m
[3][0] - m
[0][2] * m
[2][1] * m
[3][0] +
1462 m
[0][2] * m
[2][0] * m
[3][1] - m
[0][0] * m
[2][2] * m
[3][1] -
1463 m
[0][1] * m
[2][0] * m
[3][2] + m
[0][0] * m
[2][1] * m
[3][2]) * scale
;
1464 out
[3][2] = (m
[0][2] * m
[1][1] * m
[3][0] - m
[0][1] * m
[1][2] * m
[3][0] -
1465 m
[0][2] * m
[1][0] * m
[3][1] + m
[0][0] * m
[1][2] * m
[3][1] +
1466 m
[0][1] * m
[1][0] * m
[3][2] - m
[0][0] * m
[1][1] * m
[3][2]) * scale
;
1467 out
[3][3] = (m
[0][1] * m
[1][2] * m
[2][0] - m
[0][2] * m
[1][1] * m
[2][0] +
1468 m
[0][2] * m
[1][0] * m
[2][1] - m
[0][0] * m
[1][2] * m
[2][1] -
1469 m
[0][1] * m
[1][0] * m
[2][2] + m
[0][0] * m
[1][1] * m
[2][2]) * scale
;
1475 ghid_unproject_to_z_plane (int ex
, int ey
, Coord pcb_z
, Coord
*pcb_x
, Coord
*pcb_y
)
1478 float inv_mat
[2][2];
1482 ex = view_matrix[0][0] * vx +
1483 view_matrix[0][1] * vy +
1484 view_matrix[0][2] * vz +
1485 view_matrix[0][3] * 1;
1486 ey = view_matrix[1][0] * vx +
1487 view_matrix[1][1] * vy +
1488 view_matrix[1][2] * vz +
1489 view_matrix[1][3] * 1;
1490 UNKNOWN ez = view_matrix[2][0] * vx +
1491 view_matrix[2][1] * vy +
1492 view_matrix[2][2] * vz +
1493 view_matrix[2][3] * 1;
1495 ex - view_matrix[0][3] * 1
1496 - view_matrix[0][2] * vz
1497 = view_matrix[0][0] * vx +
1498 view_matrix[0][1] * vy;
1500 ey - view_matrix[1][3] * 1
1501 - view_matrix[1][2] * vz
1502 = view_matrix[1][0] * vx +
1503 view_matrix[1][1] * vy;
1506 /* NB: last_modelview_matrix is transposed in memory! */
1507 x
= (float)ex
- last_modelview_matrix
[3][0] * 1
1508 - last_modelview_matrix
[2][0] * pcb_z
;
1510 y
= (float)ey
- last_modelview_matrix
[3][1] * 1
1511 - last_modelview_matrix
[2][1] * pcb_z
;
1514 x = view_matrix[0][0] * vx +
1515 view_matrix[0][1] * vy;
1517 y = view_matrix[1][0] * vx +
1518 view_matrix[1][1] * vy;
1520 [view_matrix[0][0] view_matrix[0][1]] [vx] = [x]
1521 [view_matrix[1][0] view_matrix[1][1]] [vy] [y]
1524 mat
[0][0] = last_modelview_matrix
[0][0];
1525 mat
[0][1] = last_modelview_matrix
[1][0];
1526 mat
[1][0] = last_modelview_matrix
[0][1];
1527 mat
[1][1] = last_modelview_matrix
[1][1];
1529 /* if (determinant_2x2 (mat) < 0.00001) */
1530 /* printf ("Determinant is quite small\n"); */
1532 invert_2x2 (mat
, inv_mat
);
1534 *pcb_x
= (int)(inv_mat
[0][0] * x
+ inv_mat
[0][1] * y
);
1535 *pcb_y
= (int)(inv_mat
[1][0] * x
+ inv_mat
[1][1] * y
);
1540 ghid_event_to_pcb_coords (int event_x
, int event_y
, Coord
*pcb_x
, Coord
*pcb_y
)
1542 ghid_unproject_to_z_plane (event_x
, event_y
, 0, pcb_x
, pcb_y
);
1548 ghid_pcb_to_event_coords (Coord pcb_x
, Coord pcb_y
, int *event_x
, int *event_y
)
1550 /* NB: last_modelview_matrix is transposed in memory */
1551 float w
= last_modelview_matrix
[0][3] * (float)pcb_x
+
1552 last_modelview_matrix
[1][3] * (float)pcb_y
+
1553 last_modelview_matrix
[2][3] * 0. +
1554 last_modelview_matrix
[3][3] * 1.;
1556 *event_x
= (last_modelview_matrix
[0][0] * (float)pcb_x
+
1557 last_modelview_matrix
[1][0] * (float)pcb_y
+
1558 last_modelview_matrix
[2][0] * 0. +
1559 last_modelview_matrix
[3][0] * 1.) / w
;
1560 *event_y
= (last_modelview_matrix
[0][1] * (float)pcb_x
+
1561 last_modelview_matrix
[1][1] * (float)pcb_y
+
1562 last_modelview_matrix
[2][1] * 0. +
1563 last_modelview_matrix
[3][1] * 1.) / w
;
1569 ghid_view_2d (void *ball
, gboolean view_2d
, gpointer userdata
)
1571 global_view_2d
= view_2d
;
1572 ghid_invalidate_all ();
1576 ghid_port_rotate (void *ball
, float *quarternion
, gpointer userdata
)
1582 build_rotmatrix (view_matrix
, quarternion
);
1585 for (row
= 0; row
< 4; row
++) {
1586 printf ("[ %f", view_matrix
[row
][0]);
1587 for (column
= 1; column
< 4; column
++) {
1588 printf (",\t%f", view_matrix
[row
][column
]);
1595 ghid_invalidate_all ();
1599 #define LEAD_USER_WIDTH 0.2 /* millimeters */
1600 #define LEAD_USER_PERIOD (1000 / 20) /* 20fps (in ms) */
1601 #define LEAD_USER_VELOCITY 3. /* millimeters per second */
1602 #define LEAD_USER_ARC_COUNT 3
1603 #define LEAD_USER_ARC_SEPARATION 3. /* millimeters */
1604 #define LEAD_USER_INITIAL_RADIUS 10. /* millimetres */
1605 #define LEAD_USER_COLOR_R 1.
1606 #define LEAD_USER_COLOR_G 1.
1607 #define LEAD_USER_COLOR_B 0.
1610 draw_lead_user (render_priv
*priv
)
1613 double radius
= priv
->lead_user_radius
;
1614 double width
= MM_TO_COORD (LEAD_USER_WIDTH
);
1615 double separation
= MM_TO_COORD (LEAD_USER_ARC_SEPARATION
);
1617 if (!priv
->lead_user
)
1620 glPushAttrib (GL_CURRENT_BIT
| GL_COLOR_BUFFER_BIT
);
1621 glEnable (GL_COLOR_LOGIC_OP
);
1623 glColor3f (LEAD_USER_COLOR_R
, LEAD_USER_COLOR_G
,LEAD_USER_COLOR_B
);
1626 /* arcs at the approrpriate radii */
1628 for (i
= 0; i
< LEAD_USER_ARC_COUNT
; i
++, radius
-= separation
)
1631 radius
+= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
1633 /* Draw an arc at radius */
1634 hidgl_draw_arc (width
, priv
->lead_user_x
, priv
->lead_user_y
,
1635 radius
, radius
, 0, 360, gport
->view
.coord_per_px
);
1638 hidgl_flush_triangles (&buffer
);
1643 lead_user_cb (gpointer data
)
1645 render_priv
*priv
= data
;
1647 double elapsed_time
;
1649 /* Queue a redraw */
1650 ghid_invalidate_all ();
1653 elapsed_time
= g_timer_elapsed (priv
->lead_user_timer
, NULL
);
1654 g_timer_start (priv
->lead_user_timer
);
1656 step
= MM_TO_COORD (LEAD_USER_VELOCITY
* elapsed_time
);
1657 if (priv
->lead_user_radius
> step
)
1658 priv
->lead_user_radius
-= step
;
1660 priv
->lead_user_radius
= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
1666 ghid_lead_user_to_location (Coord x
, Coord y
)
1668 render_priv
*priv
= gport
->render_priv
;
1670 ghid_cancel_lead_user ();
1672 priv
->lead_user
= true;
1673 priv
->lead_user_x
= x
;
1674 priv
->lead_user_y
= y
;
1675 priv
->lead_user_radius
= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
1676 priv
->lead_user_timeout
= g_timeout_add (LEAD_USER_PERIOD
, lead_user_cb
, priv
);
1677 priv
->lead_user_timer
= g_timer_new ();
1681 ghid_cancel_lead_user (void)
1683 render_priv
*priv
= gport
->render_priv
;
1685 if (priv
->lead_user_timeout
)
1686 g_source_remove (priv
->lead_user_timeout
);
1688 if (priv
->lead_user_timer
)
1689 g_timer_destroy (priv
->lead_user_timer
);
1691 if (priv
->lead_user
)
1692 ghid_invalidate_all ();
1694 priv
->lead_user_timeout
= 0;
1695 priv
->lead_user_timer
= NULL
;
1696 priv
->lead_user
= false;