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
38 static hidGC current_gc
= NULL
;
40 /* Sets gport->u_gc to the "right" GC to use (wrt mask or window)
42 #define USE_GC(gc) if (!use_gc(gc)) return
44 static enum mask_mode cur_mask
= HID_MASK_OFF
;
45 static GLfloat view_matrix
[4][4] = {{1.0, 0.0, 0.0, 0.0},
48 {0.0, 0.0, 0.0, 1.0}};
49 static GLfloat last_modelview_matrix
[4][4] = {{1.0, 0.0, 0.0, 0.0},
52 {0.0, 0.0, 0.0, 1.0}};
53 static int global_view_2d
= 1;
55 typedef struct render_priv
{
56 GdkGLConfig
*glconfig
;
59 int subcomposite_stencil_bit
;
60 char *current_colorname
;
61 double current_alpha_mult
;
62 GTimer
*time_since_expose
;
64 /* Feature for leading the user to a particular location */
65 guint lead_user_timeout
;
66 GTimer
*lead_user_timer
;
68 Coord lead_user_radius
;
75 typedef struct hid_gc_struct
79 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
)
200 rv
= g_new0 (hid_gc_struct
, 1);
201 rv
->me_pointer
= &ghid_hid
;
202 rv
->colorname
= Settings
.BackgroundColor
;
203 rv
->alpha_mult
= 1.0;
208 ghid_draw_grid (BoxType
*drawn_area
)
210 if (Vz (PCB
->Grid
) < MIN_GRID_DISTANCE
)
213 if (gdk_color_parse (Settings
.GridColor
, &gport
->grid_color
))
215 gport
->grid_color
.red
^= gport
->bg_color
.red
;
216 gport
->grid_color
.green
^= gport
->bg_color
.green
;
217 gport
->grid_color
.blue
^= gport
->bg_color
.blue
;
220 glEnable (GL_COLOR_LOGIC_OP
);
223 glColor3f (gport
->grid_color
.red
/ 65535.,
224 gport
->grid_color
.green
/ 65535.,
225 gport
->grid_color
.blue
/ 65535.);
227 hidgl_draw_grid (drawn_area
);
229 glDisable (GL_COLOR_LOGIC_OP
);
233 ghid_draw_bg_image (void)
235 static GLuint texture_handle
= 0;
237 if (!ghidgui
->bg_pixbuf
)
240 if (texture_handle
== 0)
242 int width
= gdk_pixbuf_get_width (ghidgui
->bg_pixbuf
);
243 int height
= gdk_pixbuf_get_height (ghidgui
->bg_pixbuf
);
244 int rowstride
= gdk_pixbuf_get_rowstride (ghidgui
->bg_pixbuf
);
245 int bits_per_sample
= gdk_pixbuf_get_bits_per_sample (ghidgui
->bg_pixbuf
);
246 int n_channels
= gdk_pixbuf_get_n_channels (ghidgui
->bg_pixbuf
);
247 unsigned char *pixels
= gdk_pixbuf_get_pixels (ghidgui
->bg_pixbuf
);
249 g_warn_if_fail (bits_per_sample
== 8);
250 g_warn_if_fail (rowstride
== width
* n_channels
);
252 glGenTextures (1, &texture_handle
);
253 glBindTexture (GL_TEXTURE_2D
, texture_handle
);
255 /* XXX: We should proabbly determine what the maxmimum texture supported is,
256 * and if our image is larger, shrink it down using GDK pixbuf routines
257 * rather than having it fail below.
260 glTexImage2D (GL_TEXTURE_2D
, 0, GL_RGB
, width
, height
, 0,
261 (n_channels
== 4) ? GL_RGBA
: GL_RGB
, GL_UNSIGNED_BYTE
, pixels
);
264 glBindTexture (GL_TEXTURE_2D
, texture_handle
);
266 glTexEnvf (GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_DECAL
);
267 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
268 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
269 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
270 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
271 glEnable (GL_TEXTURE_2D
);
273 /* Render a quad with the background as a texture */
276 glTexCoord2d (0., 0.);
277 glVertex3i (0, 0, 0);
278 glTexCoord2d (1., 0.);
279 glVertex3i (PCB
->MaxWidth
, 0, 0);
280 glTexCoord2d (1., 1.);
281 glVertex3i (PCB
->MaxWidth
, PCB
->MaxHeight
, 0);
282 glTexCoord2d (0., 1.);
283 glVertex3i (0, PCB
->MaxHeight
, 0);
286 glDisable (GL_TEXTURE_2D
);
290 ghid_use_mask (enum mask_mode mode
)
292 static int stencil_bit
= 0;
294 if (mode
== cur_mask
)
297 /* Flush out any existing geoemtry to be rendered */
298 hidgl_flush_triangles (&buffer
);
302 case HID_MASK_BEFORE
:
303 /* The HID asks not to receive this mask type, so warn if we get it */
304 g_return_if_reached ();
307 /* Write '1' to the stencil buffer where the solder-mask should not be drawn. */
308 glColorMask (0, 0, 0, 0); /* Disable writting in color buffer */
309 glEnable (GL_STENCIL_TEST
); /* Enable Stencil test */
310 stencil_bit
= hidgl_assign_clear_stencil_bit(); /* Get a new (clean) bitplane to stencil with */
311 glStencilFunc (GL_ALWAYS
, stencil_bit
, stencil_bit
); /* Always pass stencil test, write stencil_bit */
312 glStencilMask (stencil_bit
); /* Only write to our subcompositing stencil bitplane */
313 glStencilOp (GL_KEEP
, GL_KEEP
, GL_REPLACE
); /* Stencil pass => replace stencil value (with 1) */
317 /* Drawing operations as masked to areas where the stencil buffer is '0' */
318 glColorMask (1, 1, 1, 1); /* Enable drawing of r, g, b & a */
319 glStencilFunc (GL_GEQUAL
, 0, stencil_bit
); /* Draw only where our bit of the stencil buffer is clear */
320 glStencilOp (GL_KEEP
, GL_KEEP
, GL_KEEP
); /* Stencil buffer read only */
324 /* Disable stenciling */
325 hidgl_return_stencil_bit (stencil_bit
); /* Relinquish any bitplane we previously used */
326 glDisable (GL_STENCIL_TEST
); /* Disable Stencil test */
333 /* Config helper functions for when the user changes color preferences.
334 | set_special colors used in the gtkhid.
337 set_special_grid_color (void)
339 if (!gport
->colormap
)
341 gport
->grid_color
.red
^= gport
->bg_color
.red
;
342 gport
->grid_color
.green
^= gport
->bg_color
.green
;
343 gport
->grid_color
.blue
^= gport
->bg_color
.blue
;
347 ghid_set_special_colors (HID_Attribute
* ha
)
349 if (!ha
->name
|| !ha
->value
)
351 if (!strcmp (ha
->name
, "background-color"))
353 ghid_map_color_string (*(char **) ha
->value
, &gport
->bg_color
);
354 set_special_grid_color ();
356 else if (!strcmp (ha
->name
, "off-limit-color"))
358 ghid_map_color_string (*(char **) ha
->value
, &gport
->offlimits_color
);
360 else if (!strcmp (ha
->name
, "grid-color"))
362 ghid_map_color_string (*(char **) ha
->value
, &gport
->grid_color
);
363 set_special_grid_color ();
377 set_gl_color_for_gc (hidGC gc
)
379 render_priv
*priv
= gport
->render_priv
;
380 static void *cache
= NULL
;
385 if (priv
->current_colorname
!= NULL
&&
386 strcmp (priv
->current_colorname
, gc
->colorname
) == 0 &&
387 priv
->current_alpha_mult
== gc
->alpha_mult
)
390 free (priv
->current_colorname
);
391 priv
->current_colorname
= strdup (gc
->colorname
);
392 priv
->current_alpha_mult
= gc
->alpha_mult
;
394 if (gport
->colormap
== NULL
)
395 gport
->colormap
= gtk_widget_get_colormap (gport
->top_window
);
396 if (strcmp (gc
->colorname
, "erase") == 0)
398 r
= gport
->bg_color
.red
/ 65535.;
399 g
= gport
->bg_color
.green
/ 65535.;
400 b
= gport
->bg_color
.blue
/ 65535.;
403 else if (strcmp (gc
->colorname
, "drill") == 0)
405 r
= gport
->offlimits_color
.red
/ 65535.;
406 g
= gport
->offlimits_color
.green
/ 65535.;
407 b
= gport
->offlimits_color
.blue
/ 65535.;
412 if (hid_cache_color (0, gc
->colorname
, &cval
, &cache
))
413 cc
= (ColorCache
*) cval
.ptr
;
416 cc
= (ColorCache
*) malloc (sizeof (ColorCache
));
417 memset (cc
, 0, sizeof (*cc
));
419 hid_cache_color (1, gc
->colorname
, &cval
, &cache
);
424 if (gdk_color_parse (gc
->colorname
, &cc
->color
))
425 gdk_color_alloc (gport
->colormap
, &cc
->color
);
427 gdk_color_white (gport
->colormap
, &cc
->color
);
428 cc
->red
= cc
->color
.red
/ 65535.;
429 cc
->green
= cc
->color
.green
/ 65535.;
430 cc
->blue
= cc
->color
.blue
/ 65535.;
441 if (!priv
->trans_lines
)
444 if (g
> maxi
) maxi
= g
;
445 if (b
> maxi
) maxi
= b
;
446 mult
= MIN (1 / a
, 1 / maxi
);
454 if(!priv
->in_context
)
457 hidgl_flush_triangles (&buffer
);
458 glColor4d (r
, g
, b
, a
);
462 ghid_set_color (hidGC gc
, const char *name
)
464 gc
->colorname
= name
;
465 set_gl_color_for_gc (gc
);
469 ghid_set_alpha_mult (hidGC gc
, double alpha_mult
)
471 gc
->alpha_mult
= alpha_mult
;
472 set_gl_color_for_gc (gc
);
476 ghid_set_line_cap (hidGC gc
, EndCapStyle style
)
482 ghid_set_line_width (hidGC gc
, Coord width
)
489 ghid_set_draw_xor (hidGC gc
, int xor)
491 /* NOT IMPLEMENTED */
493 /* Only presently called when setting up a crosshair GC.
494 * We manage our own drawing model for that anyway. */
498 ghid_set_draw_faded (hidGC gc
, int faded
)
500 printf ("ghid_set_draw_faded(%p,%d) -- not implemented\n", gc
, faded
);
504 ghid_set_line_cap_angle (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
506 printf ("ghid_set_line_cap_angle() -- not implemented\n");
510 ghid_invalidate_current_gc (void)
518 if (gc
->me_pointer
!= &ghid_hid
)
520 fprintf (stderr
, "Fatal: GC from another HID passed to GTK HID\n");
524 if (current_gc
== gc
)
529 set_gl_color_for_gc (gc
);
534 ghid_draw_line (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
538 hidgl_draw_line (gc
->cap
, gc
->width
, x1
, y1
, x2
, y2
, gport
->view
.coord_per_px
);
542 ghid_draw_arc (hidGC gc
, Coord cx
, Coord cy
, Coord xradius
, Coord yradius
,
543 Angle start_angle
, Angle delta_angle
)
547 hidgl_draw_arc (gc
->width
, cx
, cy
, xradius
, yradius
,
548 start_angle
, delta_angle
, gport
->view
.coord_per_px
);
552 ghid_draw_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
556 hidgl_draw_rect (x1
, y1
, x2
, y2
);
561 ghid_fill_circle (hidGC gc
, Coord cx
, Coord cy
, Coord radius
)
565 hidgl_fill_circle (cx
, cy
, radius
, gport
->view
.coord_per_px
);
570 ghid_fill_polygon (hidGC gc
, int n_coords
, Coord
*x
, Coord
*y
)
574 hidgl_fill_polygon (n_coords
, x
, y
);
578 ghid_fill_pcb_polygon (hidGC gc
, PolygonType
*poly
, const BoxType
*clip_box
)
582 hidgl_fill_pcb_polygon (poly
, clip_box
, gport
->view
.coord_per_px
);
586 ghid_thindraw_pcb_polygon (hidGC gc
, PolygonType
*poly
, const BoxType
*clip_box
)
588 common_thindraw_pcb_polygon (gc
, poly
, clip_box
);
589 ghid_set_alpha_mult (gc
, 0.25);
590 ghid_fill_pcb_polygon (gc
, poly
, clip_box
);
591 ghid_set_alpha_mult (gc
, 1.0);
595 ghid_fill_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
599 hidgl_fill_rect (x1
, y1
, x2
, y2
);
603 ghid_invalidate_lr (int left
, int right
, int top
, int bottom
)
605 ghid_invalidate_all ();
608 #define MAX_ELAPSED (50. / 1000.) /* 50ms */
610 ghid_invalidate_all ()
612 render_priv
*priv
= gport
->render_priv
;
613 double elapsed
= g_timer_elapsed (priv
->time_since_expose
, NULL
);
615 ghid_draw_area_update (gport
, NULL
);
617 if (elapsed
> MAX_ELAPSED
)
618 gdk_window_process_all_updates ();
622 ghid_notify_crosshair_change (bool changes_complete
)
624 /* We sometimes get called before the GUI is up */
625 if (gport
->drawing_area
== NULL
)
628 /* FIXME: We could just invalidate the bounds of the crosshair attached objects? */
629 ghid_invalidate_all ();
633 ghid_notify_mark_change (bool changes_complete
)
635 /* We sometimes get called before the GUI is up */
636 if (gport
->drawing_area
== NULL
)
639 /* FIXME: We could just invalidate the bounds of the mark? */
640 ghid_invalidate_all ();
644 draw_right_cross (gint x
, gint y
, gint z
)
646 glVertex3i (x
, 0, z
);
647 glVertex3i (x
, PCB
->MaxHeight
, z
);
648 glVertex3i (0, y
, z
);
649 glVertex3i (PCB
->MaxWidth
, y
, z
);
653 draw_slanted_cross (gint x
, gint y
, gint z
)
657 x0
= x
+ (PCB
->MaxHeight
- y
);
658 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
660 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
661 y0
= y
+ (PCB
->MaxWidth
- x
);
662 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
664 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
665 glVertex3i (x0
, y0
, z
);
666 glVertex3i (x1
, y1
, z
);
668 x0
= x
- (PCB
->MaxHeight
- y
);
669 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
671 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
673 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
674 y1
= y
- (PCB
->MaxWidth
- x
);
675 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
676 glVertex3i (x0
, y0
, z
);
677 glVertex3i (x1
, y1
, z
);
681 draw_dozen_cross (gint x
, gint y
, gint z
)
684 gdouble tan60
= sqrt (3);
686 x0
= x
+ (PCB
->MaxHeight
- y
) / tan60
;
687 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
689 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
690 y0
= y
+ (PCB
->MaxWidth
- x
) * tan60
;
691 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
693 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
694 glVertex3i (x0
, y0
, z
);
695 glVertex3i (x1
, y1
, z
);
697 x0
= x
+ (PCB
->MaxHeight
- y
) * tan60
;
698 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
700 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
701 y0
= y
+ (PCB
->MaxWidth
- x
) / tan60
;
702 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
704 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
705 glVertex3i (x0
, y0
, z
);
706 glVertex3i (x1
, y1
, z
);
708 x0
= x
- (PCB
->MaxHeight
- y
) / tan60
;
709 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
711 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
713 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
714 y1
= y
- (PCB
->MaxWidth
- x
) * tan60
;
715 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
716 glVertex3i (x0
, y0
, z
);
717 glVertex3i (x1
, y1
, z
);
719 x0
= x
- (PCB
->MaxHeight
- y
) * tan60
;
720 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
722 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
724 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
725 y1
= y
- (PCB
->MaxWidth
- x
) / tan60
;
726 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
727 glVertex3i (x0
, y0
, z
);
728 glVertex3i (x1
, y1
, z
);
732 draw_crosshair (render_priv
*priv
)
735 static int done_once
= 0;
736 static GdkColor cross_color
;
741 /* FIXME: when CrossColor changed from config */
742 ghid_map_color_string (Settings
.CrossColor
, &cross_color
);
745 x
= gport
->crosshair_x
;
746 y
= gport
->crosshair_y
;
749 glEnable (GL_COLOR_LOGIC_OP
);
752 glColor3f (cross_color
.red
/ 65535.,
753 cross_color
.green
/ 65535.,
754 cross_color
.blue
/ 65535.);
758 draw_right_cross (x
, y
, z
);
759 if (Crosshair
.shape
== Union_Jack_Crosshair_Shape
)
760 draw_slanted_cross (x
, y
, z
);
761 if (Crosshair
.shape
== Dozen_Crosshair_Shape
)
762 draw_dozen_cross (x
, y
, z
);
766 glDisable (GL_COLOR_LOGIC_OP
);
770 ghid_init_renderer (int *argc
, char ***argv
, GHidPort
*port
)
774 port
->render_priv
= priv
= g_new0 (render_priv
, 1);
776 priv
->time_since_expose
= g_timer_new ();
778 gtk_gl_init(argc
, argv
);
780 /* setup GL-context */
781 priv
->glconfig
= gdk_gl_config_new_by_mode (GDK_GL_MODE_RGBA
|
782 GDK_GL_MODE_STENCIL
|
786 printf ("Could not setup GL-context!\n");
787 return; /* Should we abort? */
790 /* Setup HID function pointers specific to the GL renderer*/
791 ghid_hid
.end_layer
= ghid_end_layer
;
792 ghid_hid
.fill_pcb_polygon
= ghid_fill_pcb_polygon
;
793 ghid_hid
.thindraw_pcb_polygon
= ghid_thindraw_pcb_polygon
;
797 ghid_shutdown_renderer (GHidPort
*port
)
799 ghid_cancel_lead_user ();
800 g_free (port
->render_priv
);
801 port
->render_priv
= NULL
;
805 ghid_init_drawing_widget (GtkWidget
*widget
, GHidPort
*port
)
807 render_priv
*priv
= port
->render_priv
;
809 gtk_widget_set_gl_capability (widget
,
817 ghid_drawing_area_configure_hook (GHidPort
*port
)
822 ghid_start_drawing (GHidPort
*port
)
824 GtkWidget
*widget
= port
->drawing_area
;
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
)
840 GtkWidget
*widget
= port
->drawing_area
;
841 GdkGLDrawable
*pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
843 if (gdk_gl_drawable_is_double_buffered (pGlDrawable
))
844 gdk_gl_drawable_swap_buffers (pGlDrawable
);
848 port
->render_priv
->in_context
= false;
850 /* end drawing to current GL-context */
851 gdk_gl_drawable_gl_end (pGlDrawable
);
855 ghid_screen_update (void)
861 ghid_drawing_area_expose_cb (GtkWidget
*widget
,
865 render_priv
*priv
= port
->render_priv
;
866 GtkAllocation allocation
;
874 gtk_widget_get_allocation (widget
, &allocation
);
876 ghid_start_drawing (port
);
877 hidgl_start_render ();
879 /* If we don't have any stencil bits available,
880 we can't use the hidgl polygon drawing routine */
881 /* TODO: We could use the GLU tessellator though */
882 if (hidgl_stencil_bits() == 0)
883 ghid_hid
.fill_pcb_polygon
= common_fill_pcb_polygon
;
886 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
888 glViewport (0, 0, allocation
.width
, allocation
.height
);
890 glEnable (GL_SCISSOR_TEST
);
891 glScissor (ev
->area
.x
,
892 allocation
.height
- ev
->area
.height
- ev
->area
.y
,
893 ev
->area
.width
, ev
->area
.height
);
895 glMatrixMode (GL_PROJECTION
);
897 glOrtho (0, allocation
.width
, allocation
.height
, 0, -100000, 100000);
898 glMatrixMode (GL_MODELVIEW
);
900 glTranslatef (widget
->allocation
.width
/ 2., widget
->allocation
.height
/ 2., 0);
901 glMultMatrixf ((GLfloat
*)view_matrix
);
902 glTranslatef (-widget
->allocation
.width
/ 2., -widget
->allocation
.height
/ 2., 0);
903 glScalef ((port
->view
.flip_x
? -1. : 1.) / port
->view
.coord_per_px
,
904 (port
->view
.flip_y
? -1. : 1.) / port
->view
.coord_per_px
,
905 ((port
->view
.flip_x
== port
->view
.flip_y
) ? 1. : -1.) / port
->view
.coord_per_px
);
906 glTranslatef (port
->view
.flip_x
? port
->view
.x0
- PCB
->MaxWidth
:
908 port
->view
.flip_y
? port
->view
.y0
- PCB
->MaxHeight
:
910 glGetFloatv (GL_MODELVIEW_MATRIX
, (GLfloat
*)last_modelview_matrix
);
912 glEnable (GL_STENCIL_TEST
);
913 glClearColor (port
->offlimits_color
.red
/ 65535.,
914 port
->offlimits_color
.green
/ 65535.,
915 port
->offlimits_color
.blue
/ 65535.,
919 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
920 hidgl_reset_stencil_usage ();
922 /* Disable the stencil test until we need it - otherwise it gets dirty */
923 glDisable (GL_STENCIL_TEST
);
925 glStencilFunc (GL_ALWAYS
, 0, 0);
927 /* Test the 8 corners of a cube spanning the event */
928 min_depth
= -50; /* FIXME */
929 max_depth
= 0; /* FIXME */
931 ghid_unproject_to_z_plane (ev
->area
.x
,
933 min_depth
, &new_x
, &new_y
);
934 max_x
= min_x
= new_x
;
935 max_y
= min_y
= new_y
;
937 ghid_unproject_to_z_plane (ev
->area
.x
,
939 max_depth
, &new_x
, &new_y
);
940 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
941 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
944 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
,
946 min_depth
, &new_x
, &new_y
);
947 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
948 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
950 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
, ev
->area
.y
,
951 max_depth
, &new_x
, &new_y
);
952 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
953 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
956 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
,
957 ev
->area
.y
+ ev
->area
.height
,
958 min_depth
, &new_x
, &new_y
);
959 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
960 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
962 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
,
963 ev
->area
.y
+ ev
->area
.height
,
964 max_depth
, &new_x
, &new_y
);
965 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
966 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
969 ghid_unproject_to_z_plane (ev
->area
.x
,
970 ev
->area
.y
+ ev
->area
.height
,
973 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
974 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
976 ghid_unproject_to_z_plane (ev
->area
.x
,
977 ev
->area
.y
+ ev
->area
.height
,
980 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
981 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
983 region
.X1
= min_x
; region
.X2
= max_x
+ 1;
984 region
.Y1
= min_y
; region
.Y2
= max_y
+ 1;
986 region
.X1
= MAX (0, MIN (PCB
->MaxWidth
, region
.X1
));
987 region
.X2
= MAX (0, MIN (PCB
->MaxWidth
, region
.X2
));
988 region
.Y1
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y1
));
989 region
.Y2
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y2
));
991 glColor3f (port
->bg_color
.red
/ 65535.,
992 port
->bg_color
.green
/ 65535.,
993 port
->bg_color
.blue
/ 65535.);
996 glVertex3i (0, 0, -50);
997 glVertex3i (PCB
->MaxWidth
, 0, -50);
998 glVertex3i (PCB
->MaxWidth
, PCB
->MaxHeight
, -50);
999 glVertex3i (0, PCB
->MaxHeight
, -50);
1002 ghid_draw_bg_image ();
1004 ghid_invalidate_current_gc ();
1005 hid_expose_callback (&ghid_hid
, ®ion
, 0);
1006 hidgl_flush_triangles (&buffer
);
1008 ghid_draw_grid (®ion
);
1010 ghid_invalidate_current_gc ();
1014 hidgl_flush_triangles (&buffer
);
1016 draw_crosshair (priv
);
1017 hidgl_flush_triangles (&buffer
);
1019 draw_lead_user (priv
);
1021 hidgl_finish_render ();
1022 ghid_end_drawing (port
);
1024 g_timer_start (priv
->time_since_expose
);
1029 /* This realize callback is used to work around a crash bug in some mesa
1030 * versions (observed on a machine running the intel i965 driver. It isn't
1031 * obvious why it helps, but somehow fiddling with the GL context here solves
1032 * the issue. The problem appears to have been fixed in recent mesa versions.
1035 ghid_port_drawing_realize_cb (GtkWidget
*widget
, gpointer data
)
1037 GdkGLContext
*glcontext
= gtk_widget_get_gl_context (widget
);
1038 GdkGLDrawable
*gldrawable
= gtk_widget_get_gl_drawable (widget
);
1040 if (!gdk_gl_drawable_gl_begin (gldrawable
, glcontext
))
1043 gdk_gl_drawable_gl_end (gldrawable
);
1048 ghid_pinout_preview_expose (GtkWidget
*widget
,
1051 GdkGLContext
* pGlContext
= gtk_widget_get_gl_context (widget
);
1052 GdkGLDrawable
* pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
1053 GhidPinoutPreview
*pinout
= GHID_PINOUT_PREVIEW (widget
);
1054 GtkAllocation allocation
;
1055 view_data save_view
;
1056 int save_width
, save_height
;
1057 Coord save_max_width
;
1058 Coord save_max_height
;
1061 save_view
= gport
->view
;
1062 save_width
= gport
->width
;
1063 save_height
= gport
->height
;
1064 save_max_width
= PCB
->MaxWidth
;
1065 save_max_height
= PCB
->MaxHeight
;
1067 /* Setup zoom factor for drawing routines */
1069 gtk_widget_get_allocation (widget
, &allocation
);
1070 xz
= (double) pinout
->x_max
/ allocation
.width
;
1071 yz
= (double) pinout
->y_max
/ allocation
.height
;
1073 gport
->view
.coord_per_px
= xz
;
1075 gport
->view
.coord_per_px
= yz
;
1077 gport
->width
= allocation
.width
;
1078 gport
->height
= allocation
.height
;
1079 gport
->view
.width
= allocation
.width
* gport
->view
.coord_per_px
;
1080 gport
->view
.height
= allocation
.height
* gport
->view
.coord_per_px
;
1081 gport
->view
.x0
= (pinout
->x_max
- gport
->view
.width
) / 2;
1082 gport
->view
.y0
= (pinout
->y_max
- gport
->view
.height
) / 2;
1083 PCB
->MaxWidth
= pinout
->x_max
;
1084 PCB
->MaxHeight
= pinout
->y_max
;
1086 /* make GL-context "current" */
1087 if (!gdk_gl_drawable_gl_begin (pGlDrawable
, pGlContext
)) {
1090 hidgl_start_render ();
1091 gport
->render_priv
->in_context
= true;
1093 glEnable (GL_BLEND
);
1094 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1096 glViewport (0, 0, allocation
.width
, allocation
.height
);
1098 glEnable (GL_SCISSOR_TEST
);
1099 glScissor (ev
->area
.x
,
1100 allocation
.height
- ev
->area
.height
- ev
->area
.y
,
1101 ev
->area
.width
, ev
->area
.height
);
1103 glMatrixMode (GL_PROJECTION
);
1105 glOrtho (0, allocation
.width
, allocation
.height
, 0, -100000, 100000);
1106 glMatrixMode (GL_MODELVIEW
);
1108 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
1110 glClearColor (gport
->bg_color
.red
/ 65535.,
1111 gport
->bg_color
.green
/ 65535.,
1112 gport
->bg_color
.blue
/ 65535.,
1116 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
1117 hidgl_reset_stencil_usage ();
1119 /* call the drawing routine */
1120 ghid_invalidate_current_gc ();
1122 glScalef ((gport
->view
.flip_x
? -1. : 1.) / gport
->view
.coord_per_px
,
1123 (gport
->view
.flip_y
? -1. : 1.) / gport
->view
.coord_per_px
,
1124 ((gport
->view
.flip_x
== gport
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
1125 glTranslatef (gport
->view
.flip_x
? gport
->view
.x0
- PCB
->MaxWidth
:
1127 gport
->view
.flip_y
? gport
->view
.y0
- PCB
->MaxHeight
:
1128 -gport
->view
.y0
, 0);
1130 hid_expose_callback (&ghid_hid
, NULL
, &pinout
->element
);
1131 hidgl_flush_triangles (&buffer
);
1134 if (gdk_gl_drawable_is_double_buffered (pGlDrawable
))
1135 gdk_gl_drawable_swap_buffers (pGlDrawable
);
1139 hidgl_finish_render ();
1141 /* end drawing to current GL-context */
1142 gport
->render_priv
->in_context
= false;
1143 gdk_gl_drawable_gl_end (pGlDrawable
);
1145 gport
->view
= save_view
;
1146 gport
->width
= save_width
;
1147 gport
->height
= save_height
;
1148 PCB
->MaxWidth
= save_max_width
;
1149 PCB
->MaxHeight
= save_max_height
;
1156 ghid_render_pixmap (int cx
, int cy
, double zoom
, int width
, int height
, int depth
)
1158 GdkGLConfig
*glconfig
;
1160 GdkGLPixmap
*glpixmap
;
1161 GdkGLContext
* glcontext
;
1162 GdkGLDrawable
* gldrawable
;
1163 view_data save_view
;
1164 int save_width
, save_height
;
1167 save_view
= gport
->view
;
1168 save_width
= gport
->width
;
1169 save_height
= gport
->height
;
1171 /* Setup rendering context for drawing routines
1174 glconfig
= gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB
|
1175 GDK_GL_MODE_STENCIL
|
1176 GDK_GL_MODE_SINGLE
);
1178 pixmap
= gdk_pixmap_new (NULL
, width
, height
, depth
);
1179 glpixmap
= gdk_pixmap_set_gl_capability (pixmap
, glconfig
, NULL
);
1180 gldrawable
= GDK_GL_DRAWABLE (glpixmap
);
1181 glcontext
= gdk_gl_context_new (gldrawable
, NULL
, TRUE
, GDK_GL_RGBA_TYPE
);
1183 /* Setup zoom factor for drawing routines */
1185 gport
->view
.coord_per_px
= zoom
;
1186 gport
->width
= width
;
1187 gport
->height
= height
;
1188 gport
->view
.width
= width
* gport
->view
.coord_per_px
;
1189 gport
->view
.height
= height
* gport
->view
.coord_per_px
;
1190 gport
->view
.x0
= gport
->view
.flip_x
? PCB
->MaxWidth
- cx
: cx
;
1191 gport
->view
.x0
-= gport
->view
.height
/ 2;
1192 gport
->view
.y0
= gport
->view
.flip_y
? PCB
->MaxHeight
- cy
: cy
;
1193 gport
->view
.y0
-= gport
->view
.width
/ 2;
1195 /* make GL-context "current" */
1196 if (!gdk_gl_drawable_gl_begin (gldrawable
, glcontext
)) {
1199 hidgl_start_render ();
1200 gport
->render_priv
->in_context
= true;
1202 glEnable (GL_BLEND
);
1203 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1205 glViewport (0, 0, width
, height
);
1207 glEnable (GL_SCISSOR_TEST
);
1208 glScissor (0, 0, width
, height
);
1210 glMatrixMode (GL_PROJECTION
);
1212 glOrtho (0, width
, height
, 0, -100000, 100000);
1213 glMatrixMode (GL_MODELVIEW
);
1215 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
1217 glClearColor (gport
->bg_color
.red
/ 65535.,
1218 gport
->bg_color
.green
/ 65535.,
1219 gport
->bg_color
.blue
/ 65535.,
1223 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
1224 hidgl_reset_stencil_usage ();
1226 /* call the drawing routine */
1227 ghid_invalidate_current_gc ();
1229 glScalef ((gport
->view
.flip_x
? -1. : 1.) / gport
->view
.coord_per_px
,
1230 (gport
->view
.flip_y
? -1. : 1.) / gport
->view
.coord_per_px
,
1231 ((gport
->view
.flip_x
== gport
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
1232 glTranslatef (gport
->view
.flip_x
? gport
->view
.x0
- PCB
->MaxWidth
:
1234 gport
->view
.flip_y
? gport
->view
.y0
- PCB
->MaxHeight
:
1235 -gport
->view
.y0
, 0);
1237 region
.X1
= MIN(Px(0), Px(gport
->width
+ 1));
1238 region
.Y1
= MIN(Py(0), Py(gport
->height
+ 1));
1239 region
.X2
= MAX(Px(0), Px(gport
->width
+ 1));
1240 region
.Y2
= MAX(Py(0), Py(gport
->height
+ 1));
1242 region
.X1
= MAX (0, MIN (PCB
->MaxWidth
, region
.X1
));
1243 region
.X2
= MAX (0, MIN (PCB
->MaxWidth
, region
.X2
));
1244 region
.Y1
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y1
));
1245 region
.Y2
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y2
));
1247 hid_expose_callback (&ghid_hid
, ®ion
, NULL
);
1248 hidgl_flush_triangles (&buffer
);
1253 hidgl_finish_render ();
1255 /* end drawing to current GL-context */
1256 gport
->render_priv
->in_context
= false;
1257 gdk_gl_drawable_gl_end (gldrawable
);
1259 gdk_pixmap_unset_gl_capability (pixmap
);
1261 g_object_unref (glconfig
);
1262 g_object_unref (glcontext
);
1264 gport
->view
= save_view
;
1265 gport
->width
= save_width
;
1266 gport
->height
= save_height
;
1272 ghid_request_debug_draw (void)
1274 GHidPort
*port
= gport
;
1275 GtkWidget
*widget
= port
->drawing_area
;
1276 GtkAllocation allocation
;
1278 gtk_widget_get_allocation (widget
, &allocation
);
1280 ghid_start_drawing (port
);
1281 hidgl_start_render ();
1283 glViewport (0, 0, allocation
.width
, allocation
.height
);
1285 glMatrixMode (GL_PROJECTION
);
1287 glOrtho (0, allocation
.width
, allocation
.height
, 0, 0, 100);
1288 glMatrixMode (GL_MODELVIEW
);
1290 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
1292 ghid_invalidate_current_gc ();
1294 /* Setup stenciling */
1295 glDisable (GL_STENCIL_TEST
);
1298 glScalef ((port
->view
.flip_x
? -1. : 1.) / port
->view
.coord_per_px
,
1299 (port
->view
.flip_y
? -1. : 1.) / port
->view
.coord_per_px
,
1300 ((gport
->view
.flip_x
== port
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
1301 glTranslatef (port
->view
.flip_x
? port
->view
.x0
- PCB
->MaxWidth
:
1303 port
->view
.flip_y
? port
->view
.y0
- PCB
->MaxHeight
:
1310 ghid_flush_debug_draw (void)
1312 GtkWidget
*widget
= gport
->drawing_area
;
1313 GdkGLDrawable
*pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
1315 hidgl_flush_triangles (&buffer
);
1317 if (gdk_gl_drawable_is_double_buffered (pGlDrawable
))
1318 gdk_gl_drawable_swap_buffers (pGlDrawable
);
1324 ghid_finish_debug_draw (void)
1326 hidgl_flush_triangles (&buffer
);
1329 hidgl_finish_render ();
1330 ghid_end_drawing (gport
);
1334 determinant_2x2 (float m
[2][2])
1337 det
= m
[0][0] * m
[1][1] -
1344 determinant_4x4 (float m
[4][4])
1347 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] -
1348 m
[0][3] * m
[1][1] * m
[2][2] * m
[3][0]+m
[0][1] * m
[1][3] * m
[2][2] * m
[3][0] +
1349 m
[0][2] * m
[1][1] * m
[2][3] * m
[3][0]-m
[0][1] * m
[1][2] * m
[2][3] * m
[3][0] -
1350 m
[0][3] * m
[1][2] * m
[2][0] * m
[3][1]+m
[0][2] * m
[1][3] * m
[2][0] * m
[3][1] +
1351 m
[0][3] * m
[1][0] * m
[2][2] * m
[3][1]-m
[0][0] * m
[1][3] * m
[2][2] * m
[3][1] -
1352 m
[0][2] * m
[1][0] * m
[2][3] * m
[3][1]+m
[0][0] * m
[1][2] * m
[2][3] * m
[3][1] +
1353 m
[0][3] * m
[1][1] * m
[2][0] * m
[3][2]-m
[0][1] * m
[1][3] * m
[2][0] * m
[3][2] -
1354 m
[0][3] * m
[1][0] * m
[2][1] * m
[3][2]+m
[0][0] * m
[1][3] * m
[2][1] * m
[3][2] +
1355 m
[0][1] * m
[1][0] * m
[2][3] * m
[3][2]-m
[0][0] * m
[1][1] * m
[2][3] * m
[3][2] -
1356 m
[0][2] * m
[1][1] * m
[2][0] * m
[3][3]+m
[0][1] * m
[1][2] * m
[2][0] * m
[3][3] +
1357 m
[0][2] * m
[1][0] * m
[2][1] * m
[3][3]-m
[0][0] * m
[1][2] * m
[2][1] * m
[3][3] -
1358 m
[0][1] * m
[1][0] * m
[2][2] * m
[3][3]+m
[0][0] * m
[1][1] * m
[2][2] * m
[3][3];
1364 invert_2x2 (float m
[2][2], float out
[2][2])
1366 float scale
= 1 / determinant_2x2 (m
);
1367 out
[0][0] = m
[1][1] * scale
;
1368 out
[0][1] = -m
[0][1] * scale
;
1369 out
[1][0] = -m
[1][0] * scale
;
1370 out
[1][1] = m
[0][0] * scale
;
1375 invert_4x4 (float m
[4][4], float out
[4][4])
1377 float scale
= 1 / determinant_4x4 (m
);
1379 out
[0][0] = (m
[1][2] * m
[2][3] * m
[3][1] - m
[1][3] * m
[2][2] * m
[3][1] +
1380 m
[1][3] * m
[2][1] * m
[3][2] - m
[1][1] * m
[2][3] * m
[3][2] -
1381 m
[1][2] * m
[2][1] * m
[3][3] + m
[1][1] * m
[2][2] * m
[3][3]) * scale
;
1382 out
[0][1] = (m
[0][3] * m
[2][2] * m
[3][1] - m
[0][2] * m
[2][3] * m
[3][1] -
1383 m
[0][3] * m
[2][1] * m
[3][2] + m
[0][1] * m
[2][3] * m
[3][2] +
1384 m
[0][2] * m
[2][1] * m
[3][3] - m
[0][1] * m
[2][2] * m
[3][3]) * scale
;
1385 out
[0][2] = (m
[0][2] * m
[1][3] * m
[3][1] - m
[0][3] * m
[1][2] * m
[3][1] +
1386 m
[0][3] * m
[1][1] * m
[3][2] - m
[0][1] * m
[1][3] * m
[3][2] -
1387 m
[0][2] * m
[1][1] * m
[3][3] + m
[0][1] * m
[1][2] * m
[3][3]) * scale
;
1388 out
[0][3] = (m
[0][3] * m
[1][2] * m
[2][1] - m
[0][2] * m
[1][3] * m
[2][1] -
1389 m
[0][3] * m
[1][1] * m
[2][2] + m
[0][1] * m
[1][3] * m
[2][2] +
1390 m
[0][2] * m
[1][1] * m
[2][3] - m
[0][1] * m
[1][2] * m
[2][3]) * scale
;
1391 out
[1][0] = (m
[1][3] * m
[2][2] * m
[3][0] - m
[1][2] * m
[2][3] * m
[3][0] -
1392 m
[1][3] * m
[2][0] * m
[3][2] + m
[1][0] * m
[2][3] * m
[3][2] +
1393 m
[1][2] * m
[2][0] * m
[3][3] - m
[1][0] * m
[2][2] * m
[3][3]) * scale
;
1394 out
[1][1] = (m
[0][2] * m
[2][3] * m
[3][0] - m
[0][3] * m
[2][2] * m
[3][0] +
1395 m
[0][3] * m
[2][0] * m
[3][2] - m
[0][0] * m
[2][3] * m
[3][2] -
1396 m
[0][2] * m
[2][0] * m
[3][3] + m
[0][0] * m
[2][2] * m
[3][3]) * scale
;
1397 out
[1][2] = (m
[0][3] * m
[1][2] * m
[3][0] - m
[0][2] * m
[1][3] * m
[3][0] -
1398 m
[0][3] * m
[1][0] * m
[3][2] + m
[0][0] * m
[1][3] * m
[3][2] +
1399 m
[0][2] * m
[1][0] * m
[3][3] - m
[0][0] * m
[1][2] * m
[3][3]) * scale
;
1400 out
[1][3] = (m
[0][2] * m
[1][3] * m
[2][0] - m
[0][3] * m
[1][2] * m
[2][0] +
1401 m
[0][3] * m
[1][0] * m
[2][2] - m
[0][0] * m
[1][3] * m
[2][2] -
1402 m
[0][2] * m
[1][0] * m
[2][3] + m
[0][0] * m
[1][2] * m
[2][3]) * scale
;
1403 out
[2][0] = (m
[1][1] * m
[2][3] * m
[3][0] - m
[1][3] * m
[2][1] * m
[3][0] +
1404 m
[1][3] * m
[2][0] * m
[3][1] - m
[1][0] * m
[2][3] * m
[3][1] -
1405 m
[1][1] * m
[2][0] * m
[3][3] + m
[1][0] * m
[2][1] * m
[3][3]) * scale
;
1406 out
[2][1] = (m
[0][3] * m
[2][1] * m
[3][0] - m
[0][1] * m
[2][3] * m
[3][0] -
1407 m
[0][3] * m
[2][0] * m
[3][1] + m
[0][0] * m
[2][3] * m
[3][1] +
1408 m
[0][1] * m
[2][0] * m
[3][3] - m
[0][0] * m
[2][1] * m
[3][3]) * scale
;
1409 out
[2][2] = (m
[0][1] * m
[1][3] * m
[3][0] - m
[0][3] * m
[1][1] * m
[3][0] +
1410 m
[0][3] * m
[1][0] * m
[3][1] - m
[0][0] * m
[1][3] * m
[3][1] -
1411 m
[0][1] * m
[1][0] * m
[3][3] + m
[0][0] * m
[1][1] * m
[3][3]) * scale
;
1412 out
[2][3] = (m
[0][3] * m
[1][1] * m
[2][0] - m
[0][1] * m
[1][3] * m
[2][0] -
1413 m
[0][3] * m
[1][0] * m
[2][1] + m
[0][0] * m
[1][3] * m
[2][1] +
1414 m
[0][1] * m
[1][0] * m
[2][3] - m
[0][0] * m
[1][1] * m
[2][3]) * scale
;
1415 out
[3][0] = (m
[1][2] * m
[2][1] * m
[3][0] - m
[1][1] * m
[2][2] * m
[3][0] -
1416 m
[1][2] * m
[2][0] * m
[3][1] + m
[1][0] * m
[2][2] * m
[3][1] +
1417 m
[1][1] * m
[2][0] * m
[3][2] - m
[1][0] * m
[2][1] * m
[3][2]) * scale
;
1418 out
[3][1] = (m
[0][1] * m
[2][2] * m
[3][0] - m
[0][2] * m
[2][1] * m
[3][0] +
1419 m
[0][2] * m
[2][0] * m
[3][1] - m
[0][0] * m
[2][2] * m
[3][1] -
1420 m
[0][1] * m
[2][0] * m
[3][2] + m
[0][0] * m
[2][1] * m
[3][2]) * scale
;
1421 out
[3][2] = (m
[0][2] * m
[1][1] * m
[3][0] - m
[0][1] * m
[1][2] * m
[3][0] -
1422 m
[0][2] * m
[1][0] * m
[3][1] + m
[0][0] * m
[1][2] * m
[3][1] +
1423 m
[0][1] * m
[1][0] * m
[3][2] - m
[0][0] * m
[1][1] * m
[3][2]) * scale
;
1424 out
[3][3] = (m
[0][1] * m
[1][2] * m
[2][0] - m
[0][2] * m
[1][1] * m
[2][0] +
1425 m
[0][2] * m
[1][0] * m
[2][1] - m
[0][0] * m
[1][2] * m
[2][1] -
1426 m
[0][1] * m
[1][0] * m
[2][2] + m
[0][0] * m
[1][1] * m
[2][2]) * scale
;
1432 ghid_unproject_to_z_plane (int ex
, int ey
, Coord pcb_z
, Coord
*pcb_x
, Coord
*pcb_y
)
1435 float inv_mat
[2][2];
1439 ex = view_matrix[0][0] * vx +
1440 view_matrix[0][1] * vy +
1441 view_matrix[0][2] * vz +
1442 view_matrix[0][3] * 1;
1443 ey = view_matrix[1][0] * vx +
1444 view_matrix[1][1] * vy +
1445 view_matrix[1][2] * vz +
1446 view_matrix[1][3] * 1;
1447 UNKNOWN ez = view_matrix[2][0] * vx +
1448 view_matrix[2][1] * vy +
1449 view_matrix[2][2] * vz +
1450 view_matrix[2][3] * 1;
1452 ex - view_matrix[0][3] * 1
1453 - view_matrix[0][2] * vz
1454 = view_matrix[0][0] * vx +
1455 view_matrix[0][1] * vy;
1457 ey - view_matrix[1][3] * 1
1458 - view_matrix[1][2] * vz
1459 = view_matrix[1][0] * vx +
1460 view_matrix[1][1] * vy;
1463 /* NB: last_modelview_matrix is transposed in memory! */
1464 x
= (float)ex
- last_modelview_matrix
[3][0] * 1
1465 - last_modelview_matrix
[2][0] * pcb_z
;
1467 y
= (float)ey
- last_modelview_matrix
[3][1] * 1
1468 - last_modelview_matrix
[2][1] * pcb_z
;
1471 x = view_matrix[0][0] * vx +
1472 view_matrix[0][1] * vy;
1474 y = view_matrix[1][0] * vx +
1475 view_matrix[1][1] * vy;
1477 [view_matrix[0][0] view_matrix[0][1]] [vx] = [x]
1478 [view_matrix[1][0] view_matrix[1][1]] [vy] [y]
1481 mat
[0][0] = last_modelview_matrix
[0][0];
1482 mat
[0][1] = last_modelview_matrix
[1][0];
1483 mat
[1][0] = last_modelview_matrix
[0][1];
1484 mat
[1][1] = last_modelview_matrix
[1][1];
1486 /* if (determinant_2x2 (mat) < 0.00001) */
1487 /* printf ("Determinant is quite small\n"); */
1489 invert_2x2 (mat
, inv_mat
);
1491 *pcb_x
= (int)(inv_mat
[0][0] * x
+ inv_mat
[0][1] * y
);
1492 *pcb_y
= (int)(inv_mat
[1][0] * x
+ inv_mat
[1][1] * y
);
1497 ghid_event_to_pcb_coords (int event_x
, int event_y
, Coord
*pcb_x
, Coord
*pcb_y
)
1499 ghid_unproject_to_z_plane (event_x
, event_y
, 0, pcb_x
, pcb_y
);
1505 ghid_pcb_to_event_coords (Coord pcb_x
, Coord pcb_y
, int *event_x
, int *event_y
)
1507 /* NB: last_modelview_matrix is transposed in memory */
1508 float w
= last_modelview_matrix
[0][3] * (float)pcb_x
+
1509 last_modelview_matrix
[1][3] * (float)pcb_y
+
1510 last_modelview_matrix
[2][3] * 0. +
1511 last_modelview_matrix
[3][3] * 1.;
1513 *event_x
= (last_modelview_matrix
[0][0] * (float)pcb_x
+
1514 last_modelview_matrix
[1][0] * (float)pcb_y
+
1515 last_modelview_matrix
[2][0] * 0. +
1516 last_modelview_matrix
[3][0] * 1.) / w
;
1517 *event_y
= (last_modelview_matrix
[0][1] * (float)pcb_x
+
1518 last_modelview_matrix
[1][1] * (float)pcb_y
+
1519 last_modelview_matrix
[2][1] * 0. +
1520 last_modelview_matrix
[3][1] * 1.) / w
;
1526 ghid_view_2d (void *ball
, gboolean view_2d
, gpointer userdata
)
1528 global_view_2d
= view_2d
;
1529 ghid_invalidate_all ();
1533 ghid_port_rotate (void *ball
, float *quarternion
, gpointer userdata
)
1539 build_rotmatrix (view_matrix
, quarternion
);
1542 for (row
= 0; row
< 4; row
++) {
1543 printf ("[ %f", view_matrix
[row
][0]);
1544 for (column
= 1; column
< 4; column
++) {
1545 printf (",\t%f", view_matrix
[row
][column
]);
1552 ghid_invalidate_all ();
1556 #define LEAD_USER_WIDTH 0.2 /* millimeters */
1557 #define LEAD_USER_PERIOD (1000 / 20) /* 20fps (in ms) */
1558 #define LEAD_USER_VELOCITY 3. /* millimeters per second */
1559 #define LEAD_USER_ARC_COUNT 3
1560 #define LEAD_USER_ARC_SEPARATION 3. /* millimeters */
1561 #define LEAD_USER_INITIAL_RADIUS 10. /* millimetres */
1562 #define LEAD_USER_COLOR_R 1.
1563 #define LEAD_USER_COLOR_G 1.
1564 #define LEAD_USER_COLOR_B 0.
1567 draw_lead_user (render_priv
*priv
)
1570 double radius
= priv
->lead_user_radius
;
1571 double width
= MM_TO_COORD (LEAD_USER_WIDTH
);
1572 double separation
= MM_TO_COORD (LEAD_USER_ARC_SEPARATION
);
1574 if (!priv
->lead_user
)
1577 glPushAttrib (GL_CURRENT_BIT
| GL_COLOR_BUFFER_BIT
);
1578 glEnable (GL_COLOR_LOGIC_OP
);
1580 glColor3f (LEAD_USER_COLOR_R
, LEAD_USER_COLOR_G
,LEAD_USER_COLOR_B
);
1583 /* arcs at the approrpriate radii */
1585 for (i
= 0; i
< LEAD_USER_ARC_COUNT
; i
++, radius
-= separation
)
1588 radius
+= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
1590 /* Draw an arc at radius */
1591 hidgl_draw_arc (width
, priv
->lead_user_x
, priv
->lead_user_y
,
1592 radius
, radius
, 0, 360, gport
->view
.coord_per_px
);
1595 hidgl_flush_triangles (&buffer
);
1600 lead_user_cb (gpointer data
)
1602 render_priv
*priv
= data
;
1604 double elapsed_time
;
1606 /* Queue a redraw */
1607 ghid_invalidate_all ();
1610 elapsed_time
= g_timer_elapsed (priv
->lead_user_timer
, NULL
);
1611 g_timer_start (priv
->lead_user_timer
);
1613 step
= MM_TO_COORD (LEAD_USER_VELOCITY
* elapsed_time
);
1614 if (priv
->lead_user_radius
> step
)
1615 priv
->lead_user_radius
-= step
;
1617 priv
->lead_user_radius
= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
1623 ghid_lead_user_to_location (Coord x
, Coord y
)
1625 render_priv
*priv
= gport
->render_priv
;
1627 ghid_cancel_lead_user ();
1629 priv
->lead_user
= true;
1630 priv
->lead_user_x
= x
;
1631 priv
->lead_user_y
= y
;
1632 priv
->lead_user_radius
= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
1633 priv
->lead_user_timeout
= g_timeout_add (LEAD_USER_PERIOD
, lead_user_cb
, priv
);
1634 priv
->lead_user_timer
= g_timer_new ();
1638 ghid_cancel_lead_user (void)
1640 render_priv
*priv
= gport
->render_priv
;
1642 if (priv
->lead_user_timeout
)
1643 g_source_remove (priv
->lead_user_timeout
);
1645 if (priv
->lead_user_timer
)
1646 g_timer_destroy (priv
->lead_user_timer
);
1648 if (priv
->lead_user
)
1649 ghid_invalidate_all ();
1651 priv
->lead_user_timeout
= 0;
1652 priv
->lead_user_timer
= NULL
;
1653 priv
->lead_user
= false;