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
;
76 typedef struct hid_gc_struct
80 const char *colorname
;
88 static void draw_lead_user (render_priv
*priv
);
89 static void ghid_unproject_to_z_plane (int ex
, int ey
, Coord pcb_z
, Coord
*pcb_x
, Coord
*pcb_y
);
93 start_subcomposite (void)
95 render_priv
*priv
= gport
->render_priv
;
98 /* Flush out any existing geoemtry to be rendered */
99 hidgl_flush_triangles (&buffer
);
101 glEnable (GL_STENCIL_TEST
); /* Enable Stencil test */
102 glStencilOp (GL_KEEP
, GL_KEEP
, GL_REPLACE
); /* Stencil pass => replace stencil value (with 1) */
104 stencil_bit
= hidgl_assign_clear_stencil_bit(); /* Get a new (clean) bitplane to stencil with */
105 glStencilMask (stencil_bit
); /* Only write to our subcompositing stencil bitplane */
106 glStencilFunc (GL_GREATER
, stencil_bit
, stencil_bit
); /* Pass stencil test if our assigned bit is clear */
108 priv
->subcomposite_stencil_bit
= stencil_bit
;
112 end_subcomposite (void)
114 render_priv
*priv
= gport
->render_priv
;
116 /* Flush out any existing geoemtry to be rendered */
117 hidgl_flush_triangles (&buffer
);
119 hidgl_return_stencil_bit (priv
->subcomposite_stencil_bit
); /* Relinquish any bitplane we previously used */
122 glStencilFunc (GL_ALWAYS
, 0, 0); /* Always pass stencil test */
123 glDisable (GL_STENCIL_TEST
); /* Disable Stencil test */
125 priv
->subcomposite_stencil_bit
= 0;
130 ghid_set_layer (const char *name
, int group
, int empty
)
132 render_priv
*priv
= gport
->render_priv
;
134 if (idx
>= 0 && idx
< max_group
)
136 int n
= PCB
->LayerGroups
.Number
[group
];
137 for (idx
= 0; idx
< n
-1; idx
++)
139 int ni
= PCB
->LayerGroups
.Entries
[group
][idx
];
140 if (ni
>= 0 && ni
< max_copper_layer
+ 2
141 && PCB
->Data
->Layer
[ni
].On
)
144 idx
= PCB
->LayerGroups
.Entries
[group
][idx
];
148 start_subcomposite ();
150 if (idx
>= 0 && idx
< max_copper_layer
+ 2)
152 priv
->trans_lines
= true;
153 return PCB
->Data
->Layer
[idx
].On
;
157 switch (SL_TYPE (idx
))
160 return PCB
->InvisibleObjectsOn
;
163 return TEST_FLAG (SHOWMASKFLAG
, PCB
);
166 priv
->trans_lines
= true;
168 return PCB
->ElementOn
;
177 priv
->trans_lines
= true;
185 ghid_end_layer (void)
191 ghid_destroy_gc (hidGC gc
)
201 rv
= g_new0 (hid_gc_struct
, 1);
202 rv
->me_pointer
= &ghid_hid
;
203 rv
->colorname
= Settings
.BackgroundColor
;
204 rv
->alpha_mult
= 1.0;
209 ghid_draw_grid (BoxType
*drawn_area
)
211 if (Vz (PCB
->Grid
) < MIN_GRID_DISTANCE
)
214 if (gdk_color_parse (Settings
.GridColor
, &gport
->grid_color
))
216 gport
->grid_color
.red
^= gport
->bg_color
.red
;
217 gport
->grid_color
.green
^= gport
->bg_color
.green
;
218 gport
->grid_color
.blue
^= gport
->bg_color
.blue
;
221 glEnable (GL_COLOR_LOGIC_OP
);
224 glColor3f (gport
->grid_color
.red
/ 65535.,
225 gport
->grid_color
.green
/ 65535.,
226 gport
->grid_color
.blue
/ 65535.);
228 hidgl_draw_grid (drawn_area
);
230 glDisable (GL_COLOR_LOGIC_OP
);
234 ghid_draw_bg_image (void)
236 static GLuint texture_handle
= 0;
238 if (!ghidgui
->bg_pixbuf
)
241 if (texture_handle
== 0)
243 int width
= gdk_pixbuf_get_width (ghidgui
->bg_pixbuf
);
244 int height
= gdk_pixbuf_get_height (ghidgui
->bg_pixbuf
);
245 int rowstride
= gdk_pixbuf_get_rowstride (ghidgui
->bg_pixbuf
);
246 int bits_per_sample
= gdk_pixbuf_get_bits_per_sample (ghidgui
->bg_pixbuf
);
247 int n_channels
= gdk_pixbuf_get_n_channels (ghidgui
->bg_pixbuf
);
248 unsigned char *pixels
= gdk_pixbuf_get_pixels (ghidgui
->bg_pixbuf
);
250 g_warn_if_fail (bits_per_sample
== 8);
251 g_warn_if_fail (rowstride
== width
* n_channels
);
253 glGenTextures (1, &texture_handle
);
254 glBindTexture (GL_TEXTURE_2D
, texture_handle
);
256 /* XXX: We should proabbly determine what the maxmimum texture supported is,
257 * and if our image is larger, shrink it down using GDK pixbuf routines
258 * rather than having it fail below.
261 glTexImage2D (GL_TEXTURE_2D
, 0, GL_RGB
, width
, height
, 0,
262 (n_channels
== 4) ? GL_RGBA
: GL_RGB
, GL_UNSIGNED_BYTE
, pixels
);
265 glBindTexture (GL_TEXTURE_2D
, texture_handle
);
267 glTexEnvf (GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_DECAL
);
268 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
269 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
270 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
271 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
272 glEnable (GL_TEXTURE_2D
);
274 /* Render a quad with the background as a texture */
277 glTexCoord2d (0., 0.);
278 glVertex3i (0, 0, 0);
279 glTexCoord2d (1., 0.);
280 glVertex3i (PCB
->MaxWidth
, 0, 0);
281 glTexCoord2d (1., 1.);
282 glVertex3i (PCB
->MaxWidth
, PCB
->MaxHeight
, 0);
283 glTexCoord2d (0., 1.);
284 glVertex3i (0, PCB
->MaxHeight
, 0);
287 glDisable (GL_TEXTURE_2D
);
291 ghid_use_mask (enum mask_mode mode
)
293 static int stencil_bit
= 0;
295 if (mode
== cur_mask
)
298 /* Flush out any existing geoemtry to be rendered */
299 hidgl_flush_triangles (&buffer
);
303 case HID_MASK_BEFORE
:
304 /* The HID asks not to receive this mask type, so warn if we get it */
305 g_return_if_reached ();
308 /* Write '1' to the stencil buffer where the solder-mask should not be drawn. */
309 glColorMask (0, 0, 0, 0); /* Disable writting in color buffer */
310 glEnable (GL_STENCIL_TEST
); /* Enable Stencil test */
311 stencil_bit
= hidgl_assign_clear_stencil_bit(); /* Get a new (clean) bitplane to stencil with */
312 glStencilFunc (GL_ALWAYS
, stencil_bit
, stencil_bit
); /* Always pass stencil test, write stencil_bit */
313 glStencilMask (stencil_bit
); /* Only write to our subcompositing stencil bitplane */
314 glStencilOp (GL_KEEP
, GL_KEEP
, GL_REPLACE
); /* Stencil pass => replace stencil value (with 1) */
318 /* Drawing operations as masked to areas where the stencil buffer is '0' */
319 glColorMask (1, 1, 1, 1); /* Enable drawing of r, g, b & a */
320 glStencilFunc (GL_GEQUAL
, 0, stencil_bit
); /* Draw only where our bit of the stencil buffer is clear */
321 glStencilOp (GL_KEEP
, GL_KEEP
, GL_KEEP
); /* Stencil buffer read only */
325 /* Disable stenciling */
326 hidgl_return_stencil_bit (stencil_bit
); /* Relinquish any bitplane we previously used */
327 glDisable (GL_STENCIL_TEST
); /* Disable Stencil test */
334 /* Config helper functions for when the user changes color preferences.
335 | set_special colors used in the gtkhid.
338 set_special_grid_color (void)
340 if (!gport
->colormap
)
342 gport
->grid_color
.red
^= gport
->bg_color
.red
;
343 gport
->grid_color
.green
^= gport
->bg_color
.green
;
344 gport
->grid_color
.blue
^= gport
->bg_color
.blue
;
348 ghid_set_special_colors (HID_Attribute
* ha
)
350 if (!ha
->name
|| !ha
->value
)
352 if (!strcmp (ha
->name
, "background-color"))
354 ghid_map_color_string (*(char **) ha
->value
, &gport
->bg_color
);
355 set_special_grid_color ();
357 else if (!strcmp (ha
->name
, "off-limit-color"))
359 ghid_map_color_string (*(char **) ha
->value
, &gport
->offlimits_color
);
361 else if (!strcmp (ha
->name
, "grid-color"))
363 ghid_map_color_string (*(char **) ha
->value
, &gport
->grid_color
);
364 set_special_grid_color ();
378 set_gl_color_for_gc (hidGC gc
)
380 render_priv
*priv
= gport
->render_priv
;
381 static void *cache
= NULL
;
386 if (priv
->current_colorname
!= NULL
&&
387 strcmp (priv
->current_colorname
, gc
->colorname
) == 0 &&
388 priv
->current_alpha_mult
== gc
->alpha_mult
)
391 free (priv
->current_colorname
);
392 priv
->current_colorname
= strdup (gc
->colorname
);
393 priv
->current_alpha_mult
= gc
->alpha_mult
;
395 if (gport
->colormap
== NULL
)
396 gport
->colormap
= gtk_widget_get_colormap (gport
->top_window
);
397 if (strcmp (gc
->colorname
, "erase") == 0)
399 r
= gport
->bg_color
.red
/ 65535.;
400 g
= gport
->bg_color
.green
/ 65535.;
401 b
= gport
->bg_color
.blue
/ 65535.;
404 else if (strcmp (gc
->colorname
, "drill") == 0)
406 r
= gport
->offlimits_color
.red
/ 65535.;
407 g
= gport
->offlimits_color
.green
/ 65535.;
408 b
= gport
->offlimits_color
.blue
/ 65535.;
413 if (hid_cache_color (0, gc
->colorname
, &cval
, &cache
))
414 cc
= (ColorCache
*) cval
.ptr
;
417 cc
= (ColorCache
*) malloc (sizeof (ColorCache
));
418 memset (cc
, 0, sizeof (*cc
));
420 hid_cache_color (1, gc
->colorname
, &cval
, &cache
);
425 if (gdk_color_parse (gc
->colorname
, &cc
->color
))
426 gdk_color_alloc (gport
->colormap
, &cc
->color
);
428 gdk_color_white (gport
->colormap
, &cc
->color
);
429 cc
->red
= cc
->color
.red
/ 65535.;
430 cc
->green
= cc
->color
.green
/ 65535.;
431 cc
->blue
= cc
->color
.blue
/ 65535.;
442 if (!priv
->trans_lines
)
445 if (g
> maxi
) maxi
= g
;
446 if (b
> maxi
) maxi
= b
;
447 mult
= MIN (1 / a
, 1 / maxi
);
455 if(!priv
->in_context
)
458 hidgl_flush_triangles (&buffer
);
459 glColor4d (r
, g
, b
, a
);
463 ghid_set_color (hidGC gc
, const char *name
)
465 gc
->colorname
= name
;
466 set_gl_color_for_gc (gc
);
470 ghid_set_alpha_mult (hidGC gc
, double alpha_mult
)
472 gc
->alpha_mult
= alpha_mult
;
473 set_gl_color_for_gc (gc
);
477 ghid_set_line_cap (hidGC gc
, EndCapStyle style
)
483 ghid_set_line_width (hidGC gc
, Coord width
)
490 ghid_set_draw_xor (hidGC gc
, int xor)
492 /* NOT IMPLEMENTED */
494 /* Only presently called when setting up a crosshair GC.
495 * We manage our own drawing model for that anyway. */
499 ghid_set_draw_faded (hidGC gc
, int faded
)
501 printf ("ghid_set_draw_faded(%p,%d) -- not implemented\n", gc
, faded
);
505 ghid_set_line_cap_angle (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
507 printf ("ghid_set_line_cap_angle() -- not implemented\n");
511 ghid_invalidate_current_gc (void)
519 if (gc
->me_pointer
!= &ghid_hid
)
521 fprintf (stderr
, "Fatal: GC from another HID passed to GTK HID\n");
525 if (current_gc
== gc
)
530 set_gl_color_for_gc (gc
);
535 ghid_draw_line (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
539 hidgl_draw_line (gc
->cap
, gc
->width
, x1
, y1
, x2
, y2
, gport
->view
.coord_per_px
);
543 ghid_draw_arc (hidGC gc
, Coord cx
, Coord cy
, Coord xradius
, Coord yradius
,
544 Angle start_angle
, Angle delta_angle
)
548 hidgl_draw_arc (gc
->width
, cx
, cy
, xradius
, yradius
,
549 start_angle
, delta_angle
, gport
->view
.coord_per_px
);
553 ghid_draw_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
557 hidgl_draw_rect (x1
, y1
, x2
, y2
);
562 ghid_fill_circle (hidGC gc
, Coord cx
, Coord cy
, Coord radius
)
566 hidgl_fill_circle (cx
, cy
, radius
, gport
->view
.coord_per_px
);
571 ghid_fill_polygon (hidGC gc
, int n_coords
, Coord
*x
, Coord
*y
)
575 hidgl_fill_polygon (n_coords
, x
, y
);
579 ghid_fill_pcb_polygon (hidGC gc
, PolygonType
*poly
, const BoxType
*clip_box
)
583 hidgl_fill_pcb_polygon (poly
, clip_box
, gport
->view
.coord_per_px
);
587 ghid_thindraw_pcb_polygon (hidGC gc
, PolygonType
*poly
, const BoxType
*clip_box
)
589 common_thindraw_pcb_polygon (gc
, poly
, clip_box
);
590 ghid_set_alpha_mult (gc
, 0.25);
591 gui
->graphics
->fill_pcb_polygon (gc
, poly
, clip_box
);
592 ghid_set_alpha_mult (gc
, 1.0);
596 ghid_fill_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
600 hidgl_fill_rect (x1
, y1
, x2
, y2
);
604 ghid_invalidate_lr (int left
, int right
, int top
, int bottom
)
606 ghid_invalidate_all ();
609 #define MAX_ELAPSED (50. / 1000.) /* 50ms */
611 ghid_invalidate_all ()
613 render_priv
*priv
= gport
->render_priv
;
614 double elapsed
= g_timer_elapsed (priv
->time_since_expose
, NULL
);
616 ghid_draw_area_update (gport
, NULL
);
618 if (elapsed
> MAX_ELAPSED
)
619 gdk_window_process_all_updates ();
623 ghid_notify_crosshair_change (bool changes_complete
)
625 /* We sometimes get called before the GUI is up */
626 if (gport
->drawing_area
== NULL
)
629 /* FIXME: We could just invalidate the bounds of the crosshair attached objects? */
630 ghid_invalidate_all ();
634 ghid_notify_mark_change (bool changes_complete
)
636 /* We sometimes get called before the GUI is up */
637 if (gport
->drawing_area
== NULL
)
640 /* FIXME: We could just invalidate the bounds of the mark? */
641 ghid_invalidate_all ();
645 draw_right_cross (gint x
, gint y
, gint z
)
647 glVertex3i (x
, 0, z
);
648 glVertex3i (x
, PCB
->MaxHeight
, z
);
649 glVertex3i (0, y
, z
);
650 glVertex3i (PCB
->MaxWidth
, y
, z
);
654 draw_slanted_cross (gint x
, gint y
, gint z
)
658 x0
= x
+ (PCB
->MaxHeight
- y
);
659 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
661 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
662 y0
= y
+ (PCB
->MaxWidth
- x
);
663 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
665 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
666 glVertex3i (x0
, y0
, z
);
667 glVertex3i (x1
, y1
, z
);
669 x0
= x
- (PCB
->MaxHeight
- y
);
670 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
672 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
674 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
675 y1
= y
- (PCB
->MaxWidth
- x
);
676 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
677 glVertex3i (x0
, y0
, z
);
678 glVertex3i (x1
, y1
, z
);
682 draw_dozen_cross (gint x
, gint y
, gint z
)
685 gdouble tan60
= sqrt (3);
687 x0
= x
+ (PCB
->MaxHeight
- y
) / tan60
;
688 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
690 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
691 y0
= y
+ (PCB
->MaxWidth
- x
) * tan60
;
692 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
694 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
695 glVertex3i (x0
, y0
, z
);
696 glVertex3i (x1
, y1
, z
);
698 x0
= x
+ (PCB
->MaxHeight
- y
) * tan60
;
699 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
701 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
702 y0
= y
+ (PCB
->MaxWidth
- x
) / tan60
;
703 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
705 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
706 glVertex3i (x0
, y0
, z
);
707 glVertex3i (x1
, y1
, z
);
709 x0
= x
- (PCB
->MaxHeight
- y
) / tan60
;
710 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
712 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
714 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
715 y1
= y
- (PCB
->MaxWidth
- x
) * tan60
;
716 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
717 glVertex3i (x0
, y0
, z
);
718 glVertex3i (x1
, y1
, z
);
720 x0
= x
- (PCB
->MaxHeight
- y
) * tan60
;
721 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
723 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
725 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
726 y1
= y
- (PCB
->MaxWidth
- x
) / tan60
;
727 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
728 glVertex3i (x0
, y0
, z
);
729 glVertex3i (x1
, y1
, z
);
733 draw_crosshair (render_priv
*priv
)
736 static int done_once
= 0;
737 static GdkColor cross_color
;
742 /* FIXME: when CrossColor changed from config */
743 ghid_map_color_string (Settings
.CrossColor
, &cross_color
);
746 x
= gport
->crosshair_x
;
747 y
= gport
->crosshair_y
;
750 glEnable (GL_COLOR_LOGIC_OP
);
753 glColor3f (cross_color
.red
/ 65535.,
754 cross_color
.green
/ 65535.,
755 cross_color
.blue
/ 65535.);
759 draw_right_cross (x
, y
, z
);
760 if (Crosshair
.shape
== Union_Jack_Crosshair_Shape
)
761 draw_slanted_cross (x
, y
, z
);
762 if (Crosshair
.shape
== Dozen_Crosshair_Shape
)
763 draw_dozen_cross (x
, y
, z
);
767 glDisable (GL_COLOR_LOGIC_OP
);
771 ghid_init_renderer (int *argc
, char ***argv
, GHidPort
*port
)
775 port
->render_priv
= priv
= g_new0 (render_priv
, 1);
777 priv
->time_since_expose
= g_timer_new ();
779 gtk_gl_init(argc
, argv
);
781 /* setup GL-context */
782 priv
->glconfig
= gdk_gl_config_new_by_mode (GDK_GL_MODE_RGBA
|
783 GDK_GL_MODE_STENCIL
|
787 printf ("Could not setup GL-context!\n");
788 return; /* Should we abort? */
791 /* Setup HID function pointers specific to the GL renderer*/
792 ghid_hid
.end_layer
= ghid_end_layer
;
793 ghid_graphics
.fill_pcb_polygon
= ghid_fill_pcb_polygon
;
794 ghid_graphics
.thindraw_pcb_polygon
= ghid_thindraw_pcb_polygon
;
798 ghid_shutdown_renderer (GHidPort
*port
)
800 ghid_cancel_lead_user ();
801 g_free (port
->render_priv
);
802 port
->render_priv
= NULL
;
806 ghid_init_drawing_widget (GtkWidget
*widget
, GHidPort
*port
)
808 render_priv
*priv
= port
->render_priv
;
810 gtk_widget_set_gl_capability (widget
,
818 ghid_drawing_area_configure_hook (GHidPort
*port
)
823 ghid_start_drawing (GHidPort
*port
, GtkWidget
*widget
)
825 GdkGLContext
*pGlContext
= gtk_widget_get_gl_context (widget
);
826 GdkGLDrawable
*pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
828 /* make GL-context "current" */
829 if (!gdk_gl_drawable_gl_begin (pGlDrawable
, pGlContext
))
832 port
->render_priv
->in_context
= true;
838 ghid_end_drawing (GHidPort
*port
, GtkWidget
*widget
)
840 GdkGLDrawable
*pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
842 if (gdk_gl_drawable_is_double_buffered (pGlDrawable
))
843 gdk_gl_drawable_swap_buffers (pGlDrawable
);
847 port
->render_priv
->in_context
= false;
849 /* end drawing to current GL-context */
850 gdk_gl_drawable_gl_end (pGlDrawable
);
854 ghid_screen_update (void)
860 ghid_drawing_area_expose_cb (GtkWidget
*widget
,
864 render_priv
*priv
= port
->render_priv
;
865 GtkAllocation allocation
;
873 gtk_widget_get_allocation (widget
, &allocation
);
875 ghid_start_drawing (port
, widget
);
876 hidgl_start_render ();
878 /* If we don't have any stencil bits available,
879 we can't use the hidgl polygon drawing routine */
880 /* TODO: We could use the GLU tessellator though */
881 if (hidgl_stencil_bits() == 0)
882 ghid_graphics
.fill_pcb_polygon
= common_fill_pcb_polygon
;
885 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
887 glViewport (0, 0, allocation
.width
, allocation
.height
);
889 glEnable (GL_SCISSOR_TEST
);
890 glScissor (ev
->area
.x
,
891 allocation
.height
- ev
->area
.height
- ev
->area
.y
,
892 ev
->area
.width
, ev
->area
.height
);
894 glMatrixMode (GL_PROJECTION
);
896 glOrtho (0, allocation
.width
, allocation
.height
, 0, -100000, 100000);
897 glMatrixMode (GL_MODELVIEW
);
899 glTranslatef (widget
->allocation
.width
/ 2., widget
->allocation
.height
/ 2., 0);
900 glMultMatrixf ((GLfloat
*)view_matrix
);
901 glTranslatef (-widget
->allocation
.width
/ 2., -widget
->allocation
.height
/ 2., 0);
902 glScalef ((port
->view
.flip_x
? -1. : 1.) / port
->view
.coord_per_px
,
903 (port
->view
.flip_y
? -1. : 1.) / port
->view
.coord_per_px
,
904 ((port
->view
.flip_x
== port
->view
.flip_y
) ? 1. : -1.) / port
->view
.coord_per_px
);
905 glTranslatef (port
->view
.flip_x
? port
->view
.x0
- PCB
->MaxWidth
:
907 port
->view
.flip_y
? port
->view
.y0
- PCB
->MaxHeight
:
909 glGetFloatv (GL_MODELVIEW_MATRIX
, (GLfloat
*)last_modelview_matrix
);
911 glEnable (GL_STENCIL_TEST
);
912 glClearColor (port
->offlimits_color
.red
/ 65535.,
913 port
->offlimits_color
.green
/ 65535.,
914 port
->offlimits_color
.blue
/ 65535.,
918 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
919 hidgl_reset_stencil_usage ();
921 /* Disable the stencil test until we need it - otherwise it gets dirty */
922 glDisable (GL_STENCIL_TEST
);
924 glStencilFunc (GL_ALWAYS
, 0, 0);
926 /* Test the 8 corners of a cube spanning the event */
927 min_depth
= -50; /* FIXME */
928 max_depth
= 0; /* FIXME */
930 ghid_unproject_to_z_plane (ev
->area
.x
,
932 min_depth
, &new_x
, &new_y
);
933 max_x
= min_x
= new_x
;
934 max_y
= min_y
= new_y
;
936 ghid_unproject_to_z_plane (ev
->area
.x
,
938 max_depth
, &new_x
, &new_y
);
939 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
940 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
943 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
,
945 min_depth
, &new_x
, &new_y
);
946 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
947 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
949 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
, ev
->area
.y
,
950 max_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
);
955 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
,
956 ev
->area
.y
+ ev
->area
.height
,
957 min_depth
, &new_x
, &new_y
);
958 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
959 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
961 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
,
962 ev
->area
.y
+ ev
->area
.height
,
963 max_depth
, &new_x
, &new_y
);
964 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
965 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
968 ghid_unproject_to_z_plane (ev
->area
.x
,
969 ev
->area
.y
+ ev
->area
.height
,
972 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
973 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
975 ghid_unproject_to_z_plane (ev
->area
.x
,
976 ev
->area
.y
+ ev
->area
.height
,
979 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
980 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
982 region
.X1
= min_x
; region
.X2
= max_x
+ 1;
983 region
.Y1
= min_y
; region
.Y2
= max_y
+ 1;
985 region
.X1
= MAX (0, MIN (PCB
->MaxWidth
, region
.X1
));
986 region
.X2
= MAX (0, MIN (PCB
->MaxWidth
, region
.X2
));
987 region
.Y1
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y1
));
988 region
.Y2
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y2
));
990 glColor3f (port
->bg_color
.red
/ 65535.,
991 port
->bg_color
.green
/ 65535.,
992 port
->bg_color
.blue
/ 65535.);
995 glVertex3i (0, 0, -50);
996 glVertex3i (PCB
->MaxWidth
, 0, -50);
997 glVertex3i (PCB
->MaxWidth
, PCB
->MaxHeight
, -50);
998 glVertex3i (0, PCB
->MaxHeight
, -50);
1001 ghid_draw_bg_image ();
1003 ghid_invalidate_current_gc ();
1004 hid_expose_callback (&ghid_hid
, ®ion
, 0);
1005 hidgl_flush_triangles (&buffer
);
1007 ghid_draw_grid (®ion
);
1009 ghid_invalidate_current_gc ();
1013 hidgl_flush_triangles (&buffer
);
1015 draw_crosshair (priv
);
1016 hidgl_flush_triangles (&buffer
);
1018 draw_lead_user (priv
);
1020 hidgl_finish_render ();
1021 ghid_end_drawing (port
, widget
);
1023 g_timer_start (priv
->time_since_expose
);
1028 /* This realize callback is used to work around a crash bug in some mesa
1029 * versions (observed on a machine running the intel i965 driver. It isn't
1030 * obvious why it helps, but somehow fiddling with the GL context here solves
1031 * the issue. The problem appears to have been fixed in recent mesa versions.
1034 ghid_port_drawing_realize_cb (GtkWidget
*widget
, gpointer data
)
1036 GdkGLContext
*glcontext
= gtk_widget_get_gl_context (widget
);
1037 GdkGLDrawable
*gldrawable
= gtk_widget_get_gl_drawable (widget
);
1039 if (!gdk_gl_drawable_gl_begin (gldrawable
, glcontext
))
1042 gdk_gl_drawable_gl_end (gldrawable
);
1047 ghid_pinout_preview_expose (GtkWidget
*widget
,
1050 GhidPinoutPreview
*pinout
= GHID_PINOUT_PREVIEW (widget
);
1051 GtkAllocation allocation
;
1052 view_data save_view
;
1053 int save_width
, save_height
;
1054 Coord save_max_width
;
1055 Coord save_max_height
;
1058 save_view
= gport
->view
;
1059 save_width
= gport
->width
;
1060 save_height
= gport
->height
;
1061 save_max_width
= PCB
->MaxWidth
;
1062 save_max_height
= PCB
->MaxHeight
;
1064 /* Setup zoom factor for drawing routines */
1066 gtk_widget_get_allocation (widget
, &allocation
);
1067 xz
= (double) pinout
->x_max
/ allocation
.width
;
1068 yz
= (double) pinout
->y_max
/ allocation
.height
;
1070 gport
->view
.coord_per_px
= xz
;
1072 gport
->view
.coord_per_px
= yz
;
1074 gport
->width
= allocation
.width
;
1075 gport
->height
= allocation
.height
;
1076 gport
->view
.width
= allocation
.width
* gport
->view
.coord_per_px
;
1077 gport
->view
.height
= allocation
.height
* gport
->view
.coord_per_px
;
1078 gport
->view
.x0
= (pinout
->x_max
- gport
->view
.width
) / 2;
1079 gport
->view
.y0
= (pinout
->y_max
- gport
->view
.height
) / 2;
1080 PCB
->MaxWidth
= pinout
->x_max
;
1081 PCB
->MaxHeight
= pinout
->y_max
;
1083 ghid_start_drawing (gport
, widget
);
1084 hidgl_start_render ();
1086 #if 0 /* We disable alpha blending here, as hid_expose_callback() does not
1087 * call set_layer() as appropriate for us to sub-composite rendering
1088 * from each layer when drawing a single element. If we leave alpha-
1089 * blending on, it means text and overlapping pads are rendered ugly.
1092 glEnable (GL_BLEND
);
1093 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1096 glViewport (0, 0, allocation
.width
, allocation
.height
);
1098 #if 0 /* We disable the scissor test here, as it is interacting badly with
1099 * being handed expose events which don't cover the whole window.
1100 * As we have a double-buffered GL window, we end up with unintialised
1101 * contents remaining in the unpainted areas (outside the scissor
1102 * region), and these are being flipped onto the screen.
1104 * The debugging code below shows multiple expose events when the
1105 * window is shown the first time, some of which are very small.
1107 * XXX: There is clearly a perforamnce issue here, in that we may
1108 * be rendering the preview more times, and over a larger area
1109 * than is really required.
1112 glEnable (GL_SCISSOR_TEST
);
1113 glScissor (ev
->area
.x
,
1114 allocation
.height
- ev
->area
.height
- ev
->area
.y
,
1115 ev
->area
.width
, ev
->area
.height
);
1119 printf ("EVT: %i, %i, w=%i, h=%i, Scissor setup: glScissor (%f, %f, %f, %f);\n",
1120 ev
->area
.x
, ev
->area
.y
, ev
->area
.width
, ev
->area
.height
,
1122 (double)(allocation
.height
- ev
->area
.height
- ev
->area
.y
),
1123 (double)ev
->area
.width
,
1124 (double)ev
->area
.height
);
1127 glMatrixMode (GL_PROJECTION
);
1129 glOrtho (0, allocation
.width
, allocation
.height
, 0, -100000, 100000);
1130 glMatrixMode (GL_MODELVIEW
);
1132 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
1134 glClearColor (gport
->bg_color
.red
/ 65535.,
1135 gport
->bg_color
.green
/ 65535.,
1136 gport
->bg_color
.blue
/ 65535.,
1140 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
1141 hidgl_reset_stencil_usage ();
1143 /* Disable the stencil test until we need it - otherwise it gets dirty */
1144 glDisable (GL_STENCIL_TEST
);
1146 glStencilFunc (GL_ALWAYS
, 0, 0);
1148 /* call the drawing routine */
1149 ghid_invalidate_current_gc ();
1151 glScalef ((gport
->view
.flip_x
? -1. : 1.) / gport
->view
.coord_per_px
,
1152 (gport
->view
.flip_y
? -1. : 1.) / gport
->view
.coord_per_px
,
1153 ((gport
->view
.flip_x
== gport
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
1154 glTranslatef (gport
->view
.flip_x
? gport
->view
.x0
- PCB
->MaxWidth
:
1156 gport
->view
.flip_y
? gport
->view
.y0
- PCB
->MaxHeight
:
1157 -gport
->view
.y0
, 0);
1159 hid_expose_callback (&ghid_hid
, NULL
, pinout
->element
);
1160 hidgl_flush_triangles (&buffer
);
1163 hidgl_finish_render ();
1164 ghid_end_drawing (gport
, widget
);
1166 gport
->view
= save_view
;
1167 gport
->width
= save_width
;
1168 gport
->height
= save_height
;
1169 PCB
->MaxWidth
= save_max_width
;
1170 PCB
->MaxHeight
= save_max_height
;
1177 ghid_render_pixmap (int cx
, int cy
, double zoom
, int width
, int height
, int depth
)
1179 GdkGLConfig
*glconfig
;
1181 GdkGLPixmap
*glpixmap
;
1182 GdkGLContext
* glcontext
;
1183 GdkGLDrawable
* gldrawable
;
1184 view_data save_view
;
1185 int save_width
, save_height
;
1188 save_view
= gport
->view
;
1189 save_width
= gport
->width
;
1190 save_height
= gport
->height
;
1192 /* Setup rendering context for drawing routines
1195 glconfig
= gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB
|
1196 GDK_GL_MODE_STENCIL
|
1197 GDK_GL_MODE_SINGLE
);
1199 pixmap
= gdk_pixmap_new (NULL
, width
, height
, depth
);
1200 glpixmap
= gdk_pixmap_set_gl_capability (pixmap
, glconfig
, NULL
);
1201 gldrawable
= GDK_GL_DRAWABLE (glpixmap
);
1202 glcontext
= gdk_gl_context_new (gldrawable
, NULL
, TRUE
, GDK_GL_RGBA_TYPE
);
1204 /* Setup zoom factor for drawing routines */
1206 gport
->view
.coord_per_px
= zoom
;
1207 gport
->width
= width
;
1208 gport
->height
= height
;
1209 gport
->view
.width
= width
* gport
->view
.coord_per_px
;
1210 gport
->view
.height
= height
* gport
->view
.coord_per_px
;
1211 gport
->view
.x0
= gport
->view
.flip_x
? PCB
->MaxWidth
- cx
: cx
;
1212 gport
->view
.x0
-= gport
->view
.height
/ 2;
1213 gport
->view
.y0
= gport
->view
.flip_y
? PCB
->MaxHeight
- cy
: cy
;
1214 gport
->view
.y0
-= gport
->view
.width
/ 2;
1216 /* make GL-context "current" */
1217 if (!gdk_gl_drawable_gl_begin (gldrawable
, glcontext
)) {
1220 hidgl_start_render ();
1221 gport
->render_priv
->in_context
= true;
1223 glEnable (GL_BLEND
);
1224 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1226 glViewport (0, 0, width
, height
);
1228 glEnable (GL_SCISSOR_TEST
);
1229 glScissor (0, 0, width
, height
);
1231 glMatrixMode (GL_PROJECTION
);
1233 glOrtho (0, width
, height
, 0, -100000, 100000);
1234 glMatrixMode (GL_MODELVIEW
);
1236 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
1238 glClearColor (gport
->bg_color
.red
/ 65535.,
1239 gport
->bg_color
.green
/ 65535.,
1240 gport
->bg_color
.blue
/ 65535.,
1244 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
1245 hidgl_reset_stencil_usage ();
1247 /* Disable the stencil test until we need it - otherwise it gets dirty */
1248 glDisable (GL_STENCIL_TEST
);
1250 glStencilFunc (GL_ALWAYS
, 0, 0);
1252 /* call the drawing routine */
1253 ghid_invalidate_current_gc ();
1255 glScalef ((gport
->view
.flip_x
? -1. : 1.) / gport
->view
.coord_per_px
,
1256 (gport
->view
.flip_y
? -1. : 1.) / gport
->view
.coord_per_px
,
1257 ((gport
->view
.flip_x
== gport
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
1258 glTranslatef (gport
->view
.flip_x
? gport
->view
.x0
- PCB
->MaxWidth
:
1260 gport
->view
.flip_y
? gport
->view
.y0
- PCB
->MaxHeight
:
1261 -gport
->view
.y0
, 0);
1263 region
.X1
= MIN(Px(0), Px(gport
->width
+ 1));
1264 region
.Y1
= MIN(Py(0), Py(gport
->height
+ 1));
1265 region
.X2
= MAX(Px(0), Px(gport
->width
+ 1));
1266 region
.Y2
= MAX(Py(0), Py(gport
->height
+ 1));
1268 region
.X1
= MAX (0, MIN (PCB
->MaxWidth
, region
.X1
));
1269 region
.X2
= MAX (0, MIN (PCB
->MaxWidth
, region
.X2
));
1270 region
.Y1
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y1
));
1271 region
.Y2
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y2
));
1273 hid_expose_callback (&ghid_hid
, ®ion
, NULL
);
1274 hidgl_flush_triangles (&buffer
);
1279 hidgl_finish_render ();
1281 /* end drawing to current GL-context */
1282 gport
->render_priv
->in_context
= false;
1283 gdk_gl_drawable_gl_end (gldrawable
);
1285 gdk_pixmap_unset_gl_capability (pixmap
);
1287 g_object_unref (glconfig
);
1288 g_object_unref (glcontext
);
1290 gport
->view
= save_view
;
1291 gport
->width
= save_width
;
1292 gport
->height
= save_height
;
1298 ghid_request_debug_draw (void)
1300 GHidPort
*port
= gport
;
1301 GtkWidget
*widget
= port
->drawing_area
;
1302 GtkAllocation allocation
;
1304 gtk_widget_get_allocation (widget
, &allocation
);
1306 ghid_start_drawing (port
, widget
);
1307 hidgl_start_render ();
1309 glViewport (0, 0, allocation
.width
, allocation
.height
);
1311 glMatrixMode (GL_PROJECTION
);
1313 glOrtho (0, allocation
.width
, allocation
.height
, 0, 0, 100);
1314 glMatrixMode (GL_MODELVIEW
);
1316 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
1318 ghid_invalidate_current_gc ();
1320 /* Setup stenciling */
1321 glDisable (GL_STENCIL_TEST
);
1324 glScalef ((port
->view
.flip_x
? -1. : 1.) / port
->view
.coord_per_px
,
1325 (port
->view
.flip_y
? -1. : 1.) / port
->view
.coord_per_px
,
1326 ((gport
->view
.flip_x
== port
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
1327 glTranslatef (port
->view
.flip_x
? port
->view
.x0
- PCB
->MaxWidth
:
1329 port
->view
.flip_y
? port
->view
.y0
- PCB
->MaxHeight
:
1336 ghid_flush_debug_draw (void)
1338 GtkWidget
*widget
= gport
->drawing_area
;
1339 GdkGLDrawable
*pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
1341 hidgl_flush_triangles (&buffer
);
1343 if (gdk_gl_drawable_is_double_buffered (pGlDrawable
))
1344 gdk_gl_drawable_swap_buffers (pGlDrawable
);
1350 ghid_finish_debug_draw (void)
1352 hidgl_flush_triangles (&buffer
);
1355 hidgl_finish_render ();
1356 ghid_end_drawing (gport
, gport
->drawing_area
);
1360 determinant_2x2 (float m
[2][2])
1363 det
= m
[0][0] * m
[1][1] -
1370 determinant_4x4 (float m
[4][4])
1373 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] -
1374 m
[0][3] * m
[1][1] * m
[2][2] * m
[3][0]+m
[0][1] * m
[1][3] * m
[2][2] * m
[3][0] +
1375 m
[0][2] * m
[1][1] * m
[2][3] * m
[3][0]-m
[0][1] * m
[1][2] * m
[2][3] * m
[3][0] -
1376 m
[0][3] * m
[1][2] * m
[2][0] * m
[3][1]+m
[0][2] * m
[1][3] * m
[2][0] * m
[3][1] +
1377 m
[0][3] * m
[1][0] * m
[2][2] * m
[3][1]-m
[0][0] * m
[1][3] * m
[2][2] * m
[3][1] -
1378 m
[0][2] * m
[1][0] * m
[2][3] * m
[3][1]+m
[0][0] * m
[1][2] * m
[2][3] * m
[3][1] +
1379 m
[0][3] * m
[1][1] * m
[2][0] * m
[3][2]-m
[0][1] * m
[1][3] * m
[2][0] * m
[3][2] -
1380 m
[0][3] * m
[1][0] * m
[2][1] * m
[3][2]+m
[0][0] * m
[1][3] * m
[2][1] * m
[3][2] +
1381 m
[0][1] * m
[1][0] * m
[2][3] * m
[3][2]-m
[0][0] * m
[1][1] * m
[2][3] * m
[3][2] -
1382 m
[0][2] * m
[1][1] * m
[2][0] * m
[3][3]+m
[0][1] * m
[1][2] * m
[2][0] * m
[3][3] +
1383 m
[0][2] * m
[1][0] * m
[2][1] * m
[3][3]-m
[0][0] * m
[1][2] * m
[2][1] * m
[3][3] -
1384 m
[0][1] * m
[1][0] * m
[2][2] * m
[3][3]+m
[0][0] * m
[1][1] * m
[2][2] * m
[3][3];
1390 invert_2x2 (float m
[2][2], float out
[2][2])
1392 float scale
= 1 / determinant_2x2 (m
);
1393 out
[0][0] = m
[1][1] * scale
;
1394 out
[0][1] = -m
[0][1] * scale
;
1395 out
[1][0] = -m
[1][0] * scale
;
1396 out
[1][1] = m
[0][0] * scale
;
1401 invert_4x4 (float m
[4][4], float out
[4][4])
1403 float scale
= 1 / determinant_4x4 (m
);
1405 out
[0][0] = (m
[1][2] * m
[2][3] * m
[3][1] - m
[1][3] * m
[2][2] * m
[3][1] +
1406 m
[1][3] * m
[2][1] * m
[3][2] - m
[1][1] * m
[2][3] * m
[3][2] -
1407 m
[1][2] * m
[2][1] * m
[3][3] + m
[1][1] * m
[2][2] * m
[3][3]) * scale
;
1408 out
[0][1] = (m
[0][3] * m
[2][2] * m
[3][1] - m
[0][2] * m
[2][3] * m
[3][1] -
1409 m
[0][3] * m
[2][1] * m
[3][2] + m
[0][1] * m
[2][3] * m
[3][2] +
1410 m
[0][2] * m
[2][1] * m
[3][3] - m
[0][1] * m
[2][2] * m
[3][3]) * scale
;
1411 out
[0][2] = (m
[0][2] * m
[1][3] * m
[3][1] - m
[0][3] * m
[1][2] * m
[3][1] +
1412 m
[0][3] * m
[1][1] * m
[3][2] - m
[0][1] * m
[1][3] * m
[3][2] -
1413 m
[0][2] * m
[1][1] * m
[3][3] + m
[0][1] * m
[1][2] * m
[3][3]) * scale
;
1414 out
[0][3] = (m
[0][3] * m
[1][2] * m
[2][1] - m
[0][2] * m
[1][3] * m
[2][1] -
1415 m
[0][3] * m
[1][1] * m
[2][2] + m
[0][1] * m
[1][3] * m
[2][2] +
1416 m
[0][2] * m
[1][1] * m
[2][3] - m
[0][1] * m
[1][2] * m
[2][3]) * scale
;
1417 out
[1][0] = (m
[1][3] * m
[2][2] * m
[3][0] - m
[1][2] * m
[2][3] * m
[3][0] -
1418 m
[1][3] * m
[2][0] * m
[3][2] + m
[1][0] * m
[2][3] * m
[3][2] +
1419 m
[1][2] * m
[2][0] * m
[3][3] - m
[1][0] * m
[2][2] * m
[3][3]) * scale
;
1420 out
[1][1] = (m
[0][2] * m
[2][3] * m
[3][0] - m
[0][3] * m
[2][2] * m
[3][0] +
1421 m
[0][3] * m
[2][0] * m
[3][2] - m
[0][0] * m
[2][3] * m
[3][2] -
1422 m
[0][2] * m
[2][0] * m
[3][3] + m
[0][0] * m
[2][2] * m
[3][3]) * scale
;
1423 out
[1][2] = (m
[0][3] * m
[1][2] * m
[3][0] - m
[0][2] * m
[1][3] * m
[3][0] -
1424 m
[0][3] * m
[1][0] * m
[3][2] + m
[0][0] * m
[1][3] * m
[3][2] +
1425 m
[0][2] * m
[1][0] * m
[3][3] - m
[0][0] * m
[1][2] * m
[3][3]) * scale
;
1426 out
[1][3] = (m
[0][2] * m
[1][3] * m
[2][0] - m
[0][3] * m
[1][2] * m
[2][0] +
1427 m
[0][3] * m
[1][0] * m
[2][2] - m
[0][0] * m
[1][3] * m
[2][2] -
1428 m
[0][2] * m
[1][0] * m
[2][3] + m
[0][0] * m
[1][2] * m
[2][3]) * scale
;
1429 out
[2][0] = (m
[1][1] * m
[2][3] * m
[3][0] - m
[1][3] * m
[2][1] * m
[3][0] +
1430 m
[1][3] * m
[2][0] * m
[3][1] - m
[1][0] * m
[2][3] * m
[3][1] -
1431 m
[1][1] * m
[2][0] * m
[3][3] + m
[1][0] * m
[2][1] * m
[3][3]) * scale
;
1432 out
[2][1] = (m
[0][3] * m
[2][1] * m
[3][0] - m
[0][1] * m
[2][3] * m
[3][0] -
1433 m
[0][3] * m
[2][0] * m
[3][1] + m
[0][0] * m
[2][3] * m
[3][1] +
1434 m
[0][1] * m
[2][0] * m
[3][3] - m
[0][0] * m
[2][1] * m
[3][3]) * scale
;
1435 out
[2][2] = (m
[0][1] * m
[1][3] * m
[3][0] - m
[0][3] * m
[1][1] * m
[3][0] +
1436 m
[0][3] * m
[1][0] * m
[3][1] - m
[0][0] * m
[1][3] * m
[3][1] -
1437 m
[0][1] * m
[1][0] * m
[3][3] + m
[0][0] * m
[1][1] * m
[3][3]) * scale
;
1438 out
[2][3] = (m
[0][3] * m
[1][1] * m
[2][0] - m
[0][1] * m
[1][3] * m
[2][0] -
1439 m
[0][3] * m
[1][0] * m
[2][1] + m
[0][0] * m
[1][3] * m
[2][1] +
1440 m
[0][1] * m
[1][0] * m
[2][3] - m
[0][0] * m
[1][1] * m
[2][3]) * scale
;
1441 out
[3][0] = (m
[1][2] * m
[2][1] * m
[3][0] - m
[1][1] * m
[2][2] * m
[3][0] -
1442 m
[1][2] * m
[2][0] * m
[3][1] + m
[1][0] * m
[2][2] * m
[3][1] +
1443 m
[1][1] * m
[2][0] * m
[3][2] - m
[1][0] * m
[2][1] * m
[3][2]) * scale
;
1444 out
[3][1] = (m
[0][1] * m
[2][2] * m
[3][0] - m
[0][2] * m
[2][1] * m
[3][0] +
1445 m
[0][2] * m
[2][0] * m
[3][1] - m
[0][0] * m
[2][2] * m
[3][1] -
1446 m
[0][1] * m
[2][0] * m
[3][2] + m
[0][0] * m
[2][1] * m
[3][2]) * scale
;
1447 out
[3][2] = (m
[0][2] * m
[1][1] * m
[3][0] - m
[0][1] * m
[1][2] * m
[3][0] -
1448 m
[0][2] * m
[1][0] * m
[3][1] + m
[0][0] * m
[1][2] * m
[3][1] +
1449 m
[0][1] * m
[1][0] * m
[3][2] - m
[0][0] * m
[1][1] * m
[3][2]) * scale
;
1450 out
[3][3] = (m
[0][1] * m
[1][2] * m
[2][0] - m
[0][2] * m
[1][1] * m
[2][0] +
1451 m
[0][2] * m
[1][0] * m
[2][1] - m
[0][0] * m
[1][2] * m
[2][1] -
1452 m
[0][1] * m
[1][0] * m
[2][2] + m
[0][0] * m
[1][1] * m
[2][2]) * scale
;
1458 ghid_unproject_to_z_plane (int ex
, int ey
, Coord pcb_z
, Coord
*pcb_x
, Coord
*pcb_y
)
1461 float inv_mat
[2][2];
1465 ex = view_matrix[0][0] * vx +
1466 view_matrix[0][1] * vy +
1467 view_matrix[0][2] * vz +
1468 view_matrix[0][3] * 1;
1469 ey = view_matrix[1][0] * vx +
1470 view_matrix[1][1] * vy +
1471 view_matrix[1][2] * vz +
1472 view_matrix[1][3] * 1;
1473 UNKNOWN ez = view_matrix[2][0] * vx +
1474 view_matrix[2][1] * vy +
1475 view_matrix[2][2] * vz +
1476 view_matrix[2][3] * 1;
1478 ex - view_matrix[0][3] * 1
1479 - view_matrix[0][2] * vz
1480 = view_matrix[0][0] * vx +
1481 view_matrix[0][1] * vy;
1483 ey - view_matrix[1][3] * 1
1484 - view_matrix[1][2] * vz
1485 = view_matrix[1][0] * vx +
1486 view_matrix[1][1] * vy;
1489 /* NB: last_modelview_matrix is transposed in memory! */
1490 x
= (float)ex
- last_modelview_matrix
[3][0] * 1
1491 - last_modelview_matrix
[2][0] * pcb_z
;
1493 y
= (float)ey
- last_modelview_matrix
[3][1] * 1
1494 - last_modelview_matrix
[2][1] * pcb_z
;
1497 x = view_matrix[0][0] * vx +
1498 view_matrix[0][1] * vy;
1500 y = view_matrix[1][0] * vx +
1501 view_matrix[1][1] * vy;
1503 [view_matrix[0][0] view_matrix[0][1]] [vx] = [x]
1504 [view_matrix[1][0] view_matrix[1][1]] [vy] [y]
1507 mat
[0][0] = last_modelview_matrix
[0][0];
1508 mat
[0][1] = last_modelview_matrix
[1][0];
1509 mat
[1][0] = last_modelview_matrix
[0][1];
1510 mat
[1][1] = last_modelview_matrix
[1][1];
1512 /* if (determinant_2x2 (mat) < 0.00001) */
1513 /* printf ("Determinant is quite small\n"); */
1515 invert_2x2 (mat
, inv_mat
);
1517 *pcb_x
= (int)(inv_mat
[0][0] * x
+ inv_mat
[0][1] * y
);
1518 *pcb_y
= (int)(inv_mat
[1][0] * x
+ inv_mat
[1][1] * y
);
1523 ghid_event_to_pcb_coords (int event_x
, int event_y
, Coord
*pcb_x
, Coord
*pcb_y
)
1525 ghid_unproject_to_z_plane (event_x
, event_y
, 0, pcb_x
, pcb_y
);
1531 ghid_pcb_to_event_coords (Coord pcb_x
, Coord pcb_y
, int *event_x
, int *event_y
)
1533 /* NB: last_modelview_matrix is transposed in memory */
1534 float w
= last_modelview_matrix
[0][3] * (float)pcb_x
+
1535 last_modelview_matrix
[1][3] * (float)pcb_y
+
1536 last_modelview_matrix
[2][3] * 0. +
1537 last_modelview_matrix
[3][3] * 1.;
1539 *event_x
= (last_modelview_matrix
[0][0] * (float)pcb_x
+
1540 last_modelview_matrix
[1][0] * (float)pcb_y
+
1541 last_modelview_matrix
[2][0] * 0. +
1542 last_modelview_matrix
[3][0] * 1.) / w
;
1543 *event_y
= (last_modelview_matrix
[0][1] * (float)pcb_x
+
1544 last_modelview_matrix
[1][1] * (float)pcb_y
+
1545 last_modelview_matrix
[2][1] * 0. +
1546 last_modelview_matrix
[3][1] * 1.) / w
;
1552 ghid_view_2d (void *ball
, gboolean view_2d
, gpointer userdata
)
1554 global_view_2d
= view_2d
;
1555 ghid_invalidate_all ();
1559 ghid_port_rotate (void *ball
, float *quarternion
, gpointer userdata
)
1565 build_rotmatrix (view_matrix
, quarternion
);
1568 for (row
= 0; row
< 4; row
++) {
1569 printf ("[ %f", view_matrix
[row
][0]);
1570 for (column
= 1; column
< 4; column
++) {
1571 printf (",\t%f", view_matrix
[row
][column
]);
1578 ghid_invalidate_all ();
1582 #define LEAD_USER_WIDTH 0.2 /* millimeters */
1583 #define LEAD_USER_PERIOD (1000 / 20) /* 20fps (in ms) */
1584 #define LEAD_USER_VELOCITY 3. /* millimeters per second */
1585 #define LEAD_USER_ARC_COUNT 3
1586 #define LEAD_USER_ARC_SEPARATION 3. /* millimeters */
1587 #define LEAD_USER_INITIAL_RADIUS 10. /* millimetres */
1588 #define LEAD_USER_COLOR_R 1.
1589 #define LEAD_USER_COLOR_G 1.
1590 #define LEAD_USER_COLOR_B 0.
1593 draw_lead_user (render_priv
*priv
)
1596 double radius
= priv
->lead_user_radius
;
1597 double width
= MM_TO_COORD (LEAD_USER_WIDTH
);
1598 double separation
= MM_TO_COORD (LEAD_USER_ARC_SEPARATION
);
1600 if (!priv
->lead_user
)
1603 glPushAttrib (GL_CURRENT_BIT
| GL_COLOR_BUFFER_BIT
);
1604 glEnable (GL_COLOR_LOGIC_OP
);
1606 glColor3f (LEAD_USER_COLOR_R
, LEAD_USER_COLOR_G
,LEAD_USER_COLOR_B
);
1609 /* arcs at the approrpriate radii */
1611 for (i
= 0; i
< LEAD_USER_ARC_COUNT
; i
++, radius
-= separation
)
1614 radius
+= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
1616 /* Draw an arc at radius */
1617 hidgl_draw_arc (width
, priv
->lead_user_x
, priv
->lead_user_y
,
1618 radius
, radius
, 0, 360, gport
->view
.coord_per_px
);
1621 hidgl_flush_triangles (&buffer
);
1626 lead_user_cb (gpointer data
)
1628 render_priv
*priv
= data
;
1630 double elapsed_time
;
1632 /* Queue a redraw */
1633 ghid_invalidate_all ();
1636 elapsed_time
= g_timer_elapsed (priv
->lead_user_timer
, NULL
);
1637 g_timer_start (priv
->lead_user_timer
);
1639 step
= MM_TO_COORD (LEAD_USER_VELOCITY
* elapsed_time
);
1640 if (priv
->lead_user_radius
> step
)
1641 priv
->lead_user_radius
-= step
;
1643 priv
->lead_user_radius
= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
1649 ghid_lead_user_to_location (Coord x
, Coord y
)
1651 render_priv
*priv
= gport
->render_priv
;
1653 ghid_cancel_lead_user ();
1655 priv
->lead_user
= true;
1656 priv
->lead_user_x
= x
;
1657 priv
->lead_user_y
= y
;
1658 priv
->lead_user_radius
= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
1659 priv
->lead_user_timeout
= g_timeout_add (LEAD_USER_PERIOD
, lead_user_cb
, priv
);
1660 priv
->lead_user_timer
= g_timer_new ();
1664 ghid_cancel_lead_user (void)
1666 render_priv
*priv
= gport
->render_priv
;
1668 if (priv
->lead_user_timeout
)
1669 g_source_remove (priv
->lead_user_timeout
);
1671 if (priv
->lead_user_timer
)
1672 g_timer_destroy (priv
->lead_user_timer
);
1674 if (priv
->lead_user
)
1675 ghid_invalidate_all ();
1677 priv
->lead_user_timeout
= 0;
1678 priv
->lead_user_timer
= NULL
;
1679 priv
->lead_user
= false;