11 #include "trackball.h"
20 static Axis3D axises[]={
24 { 0, 8480, 57570, 22360 },
30 { 0, 8480, 47300, 57570 },
36 { 0, 57570, 8480, 8480 },
42 cmpAxis3D(const void *a, const void *b) {
43 return ( ((Axis3D*)a)->V.z > ((Axis3D*)b)->V.z ) ? 1 : -1;
48 double minsize = fmin( XGalaxy.drawing_area->allocation.width, XGalaxy.drawing_area->allocation.height );
49 double Length = 0.4*minsize;
50 GdkGC *gc = gdk_gc_new(XGalaxy.drawing_area->window);
51 PangoLayout *pl = gtk_widget_create_pango_layout(XGalaxy.drawing_area, NULL);
55 rotate( &(axises[i].V), &(axises[i].v), &(XGalaxy.angle) );
56 vector_mul( &(axises[i].V), &(axises[i].V), Length );
59 qsort(axises, 3, sizeof(Axis3D), cmpAxis3D);
65 XGalaxy.drawing_area->allocation.width/2,
66 XGalaxy.drawing_area->allocation.height/2,
67 XGalaxy.drawing_area->allocation.width/2 + axises[i].V.x,
68 XGalaxy.drawing_area->allocation.height/2 - axises[i].V.y,
71 gdk_gc_set_rgb_fg_color(gc, &(axises[i].color));
72 pango_layout_set_text(pl, axises[i].name, -1);
76 XGalaxy.drawing_area->allocation.width/2 + axises[i].V.x,
77 XGalaxy.drawing_area->allocation.height/2 - axises[i].V.y,
82 g_object_unref(G_OBJECT(pl));
83 g_object_unref(G_OBJECT(gc));
92 for(i=0;i<XGalaxy.nentry;i++) {
93 rotate( &(XGalaxy.entry[i].a), &(XGalaxy.entry[i].c), &(XGalaxy.angle) );
94 if ( fabs(XGalaxy.entry[i].a.x) > max )
95 max = fabs(XGalaxy.entry[i].a.x);
96 if ( fabs(XGalaxy.entry[i].a.y) > max )
97 max = fabs(XGalaxy.entry[i].a.y);
98 if ( fabs(XGalaxy.entry[i].a.z) > max )
99 max = fabs(XGalaxy.entry[i].a.z);
102 XGalaxy.Scale = 1.0/(3.0*max);
106 cmpStar(const void *a, const void *b) {
107 return ( ((Star*)a)->a.z > ((Star*)b)->a.z ) ? 1 : -1;
110 #define MIN_BRIGHT (0.4)
117 double minsize = fmin( XGalaxy.drawing_area->allocation.width, XGalaxy.drawing_area->allocation.height );
118 double r, brightness;
119 GdkGC *gc = gdk_gc_new(XGalaxy.drawing_area->window);
121 if ( !XGalaxy.trace ) {
122 gdk_draw_rectangle (XGalaxy.pixmap,
123 XGalaxy.drawing_area->style->white_gc,
126 XGalaxy.drawing_area->allocation.width,
127 XGalaxy.drawing_area->allocation.height
129 if ( XGalaxy.drawaxis) drawAxis();
132 if ( XGalaxy.runing ) {
133 pthread_mutex_lock(&(XGalaxy.mutex));
134 memcpy( XGalaxy.tmpentry, XGalaxy.galaxy.stars, sizeof(Star)*XGalaxy.galaxy.nstars );
135 pthread_mutex_unlock(&(XGalaxy.mutex));
137 for(i=0;i<XGalaxy.nentry;i++)
138 rotate( &(XGalaxy.tmpentry[i].a), &(XGalaxy.tmpentry[i].c), &(XGalaxy.angle) );
140 qsort(XGalaxy.tmpentry, XGalaxy.nentry, sizeof(Star), cmpStar);
142 for(i=0;i<XGalaxy.nentry;i++) {
143 r = (10 + (10*XGalaxy.Scale*XGalaxy.tmpentry[i].a.z))/2.0;
145 brightness = MIN_BRIGHT + (1.0-MIN_BRIGHT)*(1.0 + XGalaxy.Scale*XGalaxy.tmpentry[i].a.z) / 2.0;
146 if ( brightness < MIN_BRIGHT ) brightness = MIN_BRIGHT;
147 if ( brightness > 1.0 ) brightness = 1.0;
150 ((double)XGalaxy.drawing_area->allocation.width)/2.0 + (minsize*XGalaxy.Scale*XGalaxy.tmpentry[i].a.x),
151 ((double)XGalaxy.drawing_area->allocation.height)/2.0 - (minsize*XGalaxy.Scale*XGalaxy.tmpentry[i].a.y),
158 g_object_unref(G_OBJECT(gc));
163 GdkRectangle update_rect;
169 update_rect.width = XGalaxy.drawing_area->allocation.width;
170 update_rect.height = XGalaxy.drawing_area->allocation.height;
172 gdk_window_invalidate_rect (XGalaxy.drawing_area->window, &update_rect, FALSE);
176 angle_changed(GtkRange *range, gpointer user_data) {
177 double angle = gtk_range_get_value(range)*M_PI/180.0;
178 Quaternion old, newquaternion;
180 if (XGalaxy.locksignal)
184 XGalaxy.locksignal=1;
185 switch((int)user_data) {
186 case 'X': gtk_range_set_value(range, XGalaxy.Xangle*180.0/M_PI); break;
187 case 'Y': gtk_range_set_value(range, XGalaxy.Yangle*180.0/M_PI); break;
188 case 'Z': gtk_range_set_value(range, XGalaxy.Zangle*180.0/M_PI); break;
191 XGalaxy.locksignal=0;
195 memcpy(&old, &(XGalaxy.angle), sizeof(old));
196 memset(&newquaternion, 0 , sizeof(newquaternion));
197 switch( (int)user_data ) {
199 newquaternion.d.x = sin( (angle-XGalaxy.Xangle)/2.0 );
200 newquaternion.w = cos( (angle-XGalaxy.Xangle)/2.0 );
201 XGalaxy.Xangle=angle;
204 newquaternion.d.y = sin( (angle-XGalaxy.Yangle)/2.0 );
205 newquaternion.w = cos( (angle-XGalaxy.Yangle)/2.0 );
206 XGalaxy.Yangle=angle;
209 newquaternion.d.z = sin( (angle-XGalaxy.Zangle)/2.0 );
210 newquaternion.w = cos( (angle-XGalaxy.Zangle)/2.0 );
211 XGalaxy.Zangle=angle;
213 default: g_print("Unknown axis: %c\n", (char)(int)user_data);
216 //quater_vmul( &(XGalaxy.angle), &old, &newquaternion );
217 quater_vmul( &(XGalaxy.angle), &newquaternion, &old );
224 if ( !XGalaxy.pixmap )
226 gdk_draw_rectangle (XGalaxy.pixmap,
227 XGalaxy.drawing_area->style->white_gc,
230 XGalaxy.drawing_area->allocation.width,
231 XGalaxy.drawing_area->allocation.height);
232 if ( XGalaxy.drawaxis ) drawAxis();
236 expose_event( GtkWidget *widget, GdkEventExpose *event ) {
237 /* draw only last expose */
238 if ( event->count > 0)
242 gdk_draw_pixmap(widget->window,
243 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
245 event->area.x, event->area.y,
246 event->area.x, event->area.y,
247 event->area.width, event->area.height);
253 configure_event( GtkWidget *widget, GdkEventConfigure *event ) {
255 g_object_unref(XGalaxy.pixmap);
257 XGalaxy.pixmap = gdk_pixmap_new(widget->window,
258 widget->allocation.width,
259 widget->allocation.height,
268 mouse_motion_notify(GtkWidget *widget, GdkEventMotion *event) {
271 GdkModifierType state = 0;
273 if (XGalaxy.locksignal || XGalaxy.trace )
277 gdk_window_get_pointer(event->window, &x, &y, &state);
281 state = event->state;
283 if (state & GDK_BUTTON1_MASK) {
284 double width, height;
288 width = widget->allocation.width;
289 height = widget->allocation.height;
290 trackball( &(XGalaxy.motion),
291 (2.0*XGalaxy.beginx - width) / width,
292 ( height - 2.0*XGalaxy.beginy) / height,
293 ( 2.0*x - width) / width,
294 ( height - 2.0*y) / height );
296 memcpy(&old, &(XGalaxy.angle), sizeof(old));
297 //quater_vmul( &(XGalaxy.angle), &old, &(XGalaxy.motion) );
298 quater_vmul( &(XGalaxy.angle), &(XGalaxy.motion), &old );
300 XGalaxy.locksignal=1;
301 quater_to_angles( &(XGalaxy.angle), &angles);
302 XGalaxy.Xangle = angles.x;
303 gtk_range_set_value(GTK_RANGE(XGalaxy.XSlider), angles.x*180.0/M_PI);
304 XGalaxy.Yangle = angles.y;
305 gtk_range_set_value(GTK_RANGE(XGalaxy.YSlider), angles.y*180.0/M_PI);
306 XGalaxy.Zangle = angles.z;
307 gtk_range_set_value(GTK_RANGE(XGalaxy.ZSlider), angles.z*180.0/M_PI);
308 XGalaxy.locksignal=0;