1 /*     WMGlobe 1.3  -  All the Earth on a WMaker Icon
2  *     copyright (C) 1998,99,2000,01 Jerome Dumonteil <jerome.dumonteil@linuxfr.org>
3  *
4  *     This program is free software; you can redistribute it and/or modify
5  *     it under the terms of the GNU General Public License as published by
6  *     the Free Software Foundation; either version 2 of the License, or
7  *     (at your option) any later version.
8  *
9  *     This program is distributed in the hope that it will be useful,
10  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *     GNU General Public License for more details.
13  *
14  *     You should have received a copy of the GNU General Public License
15  *     along with this program; if not, write to the Free Software
16  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  ***************************************************************************/
18 /* this code was based on XGlobe :
19    renderer.cpp
20    *
21    * This file is part of XGlobe. See README for details.
22    *
23    * Copyright (C) 1998 Thorsten Scheuermann
24    *
25    * This program is free software; you can redistribute it and/or modify
26    * it under the terms of the GNU General Public Licenses as published by
27    * the Free Software Foundation.
28    ************************************************************************/
29 /*
30    Some parts of this files should be rewritten to not depend on
31    WindowMaker version
32 */
33 
34 #include "wmglobe.h"
35 
36 /*
37  * variables globales
38  */
39 
40 double solu[DIAMETRE][DIAMETRE][3];
41 int tabsolu[DIAMETRE][DIAMETRE];
42 double moon_lat,moon_long;
43 struct timeval tlast, tnext, trend, tdelay, tini, tbase;
44 time_t tsunpos;
45 double center_dist;
46 double light_x, light_y, light_z;	/* vector of sunlight with lengt 1 */
47 double c_coef, b_coef;
48 int radius_proj, aml;
49 
50 static RColor mygetMapColorLinear
51     (double longitude, double latitude, double angle);
52 
53 /*
54  * static RColor getMapColor(double longitude, double latitude, double angle);
55  */
56 
57 static void randomPosition();
58 void setViewPos(double lat, double lon);
59 static void myRPutPixel(int x, int y, RColor * color);
60 #ifdef WITH_MARKERS
61 #if (WITH_MARKERS == 1)
62 static void invertPixel(int x, int y);
63 static void put_cross(int x, int y);
64 static void put_dot_cross(int x, int y, RColor * color);
65 #endif
66 #endif
67 static void getquarter(RImage * image, int x, int y, MPO * m[4], int dx,
68 		       int dy);
69 static void updateTime(int force);
70 static struct timeval timeaccel(struct timeval t);
71 
72 
73 
74 
75 
76 
timeaccel(struct timeval t)77 struct timeval timeaccel(struct timeval t)
78 {
79     struct timeval at;
80     double rr;
81 
82     t = diftimev(t, tini);
83     rr = floor((double) t.tv_sec * time_multi +
84 	       (double) t.tv_usec * time_multi / 1000000.);
85 /*** something bad may appen if time_multi=max after 41 minutes (overflow) ***/
86     while (rr > (double) LONG_MAX)
87 	rr -= (2.0 * (double) LONG_MAX + 1.0);
88     at.tv_sec = (int) rr;
89     at.tv_usec = (int) (t.tv_usec * time_multi) % 1000000;
90     return addtimev(at, tbase);
91 }
92 
93 
94 
95 
96 
97 
myRPutPixel(int x,int y,RColor * color)98 static void myRPutPixel(int x, int y, RColor * color)
99 {
100     int ofs;
101     unsigned char *sr, *sg, *sb;
102 
103     ofs = (y * DIAMETRE + x) * 3;
104     sr = small->data + (ofs++);
105     sg = small->data + (ofs++);
106     sb = small->data + (ofs);
107 
108     *sr = color->red;
109     *sg = color->green;
110     *sb = color->blue;
111     return;
112 }
113 
114 
115 
116 
117 
118 
119 #if WITH_MARKERS
invertPixel(int x,int y)120 static void invertPixel(int x, int y)
121 {
122     int ofs;
123     unsigned char *sr, *sg, *sb;
124 
125     ofs = (y * DIAMETRE + x) * 3;
126     sr = small->data + (ofs++);
127     sg = small->data + (ofs++);
128     sb = small->data + (ofs);
129 
130 #if ( CROSS_INVERT == 1 )
131     *sr = 255 - *sr;
132     *sg = 255 - *sg;
133     *sb = 255 - *sb;
134 #else
135     if (*sb > 127 || *sg > 127 || *sr > 127)
136 	*sr = *sg = *sb = 0;
137     else
138 	*sr = *sg = *sb = 255;
139 #endif
140     return;
141 }
142 
143 #define T_CADRE(x,y) ((x) < DIAMETRE && (x) >= 0 \
144 && (y) < DIAMETRE && (y) >= 0 && tabsolu[(x)][(y)])
145 
146 
147 
148 
149 
put_cross(int x,int y)150 static void put_cross(int x, int y)
151 {
152     int i, x_cross, y_cross;
153 
154     if (T_CADRE(x, y)) {
155 	if (!fun && sens != 1) {
156 	    x = DIAMETRE - 1 - x;
157 	    y = DIAMETRE - 1 - y;
158 	}
159 	for (i = 2; i <= CROSS_LENGTH; i++) {
160 	    x_cross = x + i;
161 	    y_cross = y;
162 	    if (T_CADRE(x_cross, y_cross))
163 		invertPixel(x_cross, y_cross);
164 	    x_cross = x - i;
165 
166 	    if (T_CADRE(x_cross, y_cross))
167 		invertPixel(x_cross, y_cross);
168 	    x_cross = x;
169 	    y_cross = y - i;
170 	    if (T_CADRE(x_cross, y_cross))
171 		invertPixel(x_cross, y_cross);
172 
173 	    y_cross = y + i;
174 	    if (T_CADRE(x_cross, y_cross))
175 		invertPixel(x_cross, y_cross);
176 	}
177     }
178 }
179 
180 
181 
182 
183 
184 
185 
186 
put_dot_cross(int x,int y,RColor * color)187 static void put_dot_cross(int x, int y, RColor * color)
188 {
189     int i, x_cross, y_cross;
190 
191     if (T_CADRE(x, y)) {
192 	if (!fun && sens != 1) {
193 	    x = DIAMETRE - 1 - x;
194 	    y = DIAMETRE - 1 - y;
195 	}
196 	for (i = 2; i <= CROSS_LENGTH; i += 2) {
197 	    x_cross = x + i;
198 	    y_cross = y;
199 	    if (T_CADRE(x_cross, y_cross))
200 		invertPixel(x_cross, y_cross);
201 	    x_cross = x - i;
202 
203 	    if (T_CADRE(x_cross, y_cross))
204 		invertPixel(x_cross, y_cross);
205 	    x_cross = x;
206 	    y_cross = y - i;
207 	    if (T_CADRE(x_cross, y_cross))
208 		invertPixel(x_cross, y_cross);
209 
210 	    y_cross = y + i;
211 	    if (T_CADRE(x_cross, y_cross))
212 		invertPixel(x_cross, y_cross);
213 
214 	    x_cross = x + i + 1;
215 	    y_cross = y;
216 	    if (T_CADRE(x_cross, y_cross))
217 		myRPutPixel(x_cross, y_cross, color);
218 	    x_cross = x - i - 1;
219 
220 	    if (T_CADRE(x_cross, y_cross))
221 		myRPutPixel(x_cross, y_cross, color);
222 	    x_cross = x;
223 	    y_cross = y - i - 1;
224 	    if (T_CADRE(x_cross, y_cross))
225 		myRPutPixel(x_cross, y_cross, color);
226 
227 	    y_cross = y + i + 1;
228 	    if (T_CADRE(x_cross, y_cross))
229 		myRPutPixel(x_cross, y_cross, color);
230 	}
231     }
232 }
233 #endif
234 
235 
236 
237 
238 
239 
240 
241 
getquarter(RImage * image,int x,int y,MPO * m[4],int dx,int dy)242 static void getquarter(RImage * image, int x, int y, MPO * m[4], int dx,
243 		       int dy)
244 {
245     int xx;
246     register int ofs;
247 
248 /*** hope this is faster than calculation with floats .... ****/
249 
250     x %= image->width;
251     xx = x;
252     y %= image->height;
253     ofs = (y * image->width + x) * 3;
254     m[0]->r = image->data[ofs++];
255     m[0]->g = image->data[ofs++];
256     m[0]->b = image->data[ofs];
257 
258     xx++;
259     xx %= image->width;
260     ofs = (y * image->width + xx) * 3;
261     m[1]->r = image->data[ofs++];
262     m[1]->g = image->data[ofs++];
263     m[1]->b = image->data[ofs];
264 
265     y++;
266     y %= image->height;
267     ofs = (y * image->width + x) * 3;
268     m[2]->r = image->data[ofs++];
269     m[2]->g = image->data[ofs++];
270     m[2]->b = image->data[ofs];
271 
272     ofs = (y * image->width + xx) * 3;
273     m[3]->r = image->data[ofs++];
274     m[3]->g = image->data[ofs++];
275     m[3]->b = image->data[ofs];
276 
277 
278 /*
279  * m[0]->r=((m[0]->r*(256-dx)*(256-dy))+
280  *      (m[1]->r*dx*(256-dy))+
281  *      (m[2]->r*(256-dx)*dy)+
282  *      (m[3]->r*dx*dy))>>16;
283  * m[0]->g=((m[0]->g*(256-dx)*(256-dy))+
284  *      (m[1]->g*dx*(256-dy))+
285  *      (m[2]->g*(256-dx)*dy)+
286  *      (m[3]->g*dx*dy))>>16;
287  * m[0]->b=((m[0]->b*(256-dx)*(256-dy))+
288  *      (m[1]->b*dx*(256-dy))+
289  *      (m[2]->b*(256-dx)*dy)+
290  *      (m[3]->b*dx*dy))>>16;
291  */
292 
293     if ((ofs = m[1]->r - m[0]->r) != 0)
294 	m[0]->r += (ofs * dx) >> 8;
295     if ((ofs = m[1]->g - m[0]->g) != 0)
296 	m[0]->g += (ofs * dx) >> 8;
297     if ((ofs = m[1]->b - m[0]->b) != 0)
298 	m[0]->b += (ofs * dx) >> 8;
299 
300     if ((ofs = m[3]->r - m[2]->r) != 0)
301 	m[2]->r += (ofs * dx) >> 8;
302     if ((ofs = m[3]->g - m[2]->g) != 0)
303 	m[2]->g += (ofs * dx) >> 8;
304     if ((ofs = m[3]->b - m[2]->b) != 0)
305 	m[2]->b += (ofs * dx) >> 8;
306 
307     if ((ofs = m[2]->r - m[0]->r) != 0)
308 	m[0]->r += (ofs * dy) >> 8;
309     if ((ofs = m[2]->g - m[0]->g) != 0)
310 	m[0]->g += (ofs * dy) >> 8;
311     if ((ofs = m[2]->b - m[0]->b) != 0)
312 	m[0]->b += (ofs * dy) >> 8;
313 
314     return;
315 }
316 
317 
318 
319 
320 
321 
322 
323 
324 
calcDistance()325 void calcDistance()
326 {
327     double tan_a;
328 
329     tan_a = (zoom * DIAMETRE / 2.0) / proj_dist;
330 /*
331  *     distance of camera to center of earth ( = coordinate origin)
332  */
333     center_dist = radius / sin(atan(tan_a));
334     c_coef = center_dist * center_dist - radius * radius;
335     solution = FALSE;
336     return;
337 }
338 
339 
340 
341 
342 
343 
344 
345 
346 
renderFrame()347 void renderFrame()
348 {
349     int py, px;
350     RColor teinte;
351 
352     double dir_x, dir_y, dir_z;	/* direction of cast ray */
353 
354     double hit_x, hit_y, hit_z;	/* hit position on earth surface */
355 
356     double hit2_x, hit2_y, hit2_z;	/* mirrored hit position on earth surface */
357 
358     double sp_x, sp_y, sp_z;	/* intersection point of globe and ray */
359 
360     double a;			/*  coeff. of quardatic equation */
361 
362     double udroot;		/*  racine */
363     double wurzel;
364     double r;			/* r' */
365 
366     double s1, s2, s;		/*distance between intersections and
367 				   camera position */
368 
369     double longitude, latitude;	/* coordinates of hit position */
370 
371     double light_angle;		/* cosine of angle between sunlight and
372 				   surface normal */
373 
374     int startx, endx;		/* the region to be painted */
375 
376     int starty, endy;
377 
378     double m11;
379     double m12;
380     double m13;
381     double m21;
382     double m22;
383     double m23;
384     double m31;
385     double m32;
386     double m33;
387 
388     a = dir_x = dir_y = 0;
389     dir_z = -proj_dist;
390 
391 #ifdef DEBUG
392     fprintf(stdout, "solution : %d\n", solution);
393 #endif
394     /*
395      * clear image
396      */
397     if (solution == FALSE)
398 	RClearImage(small, &noir);
399     /*
400      *  rotation matrix
401      */
402 
403     m11 = cos(v_long);
404     m22 = cos(v_lat);
405     m23 = sin(v_lat);
406     m31 = -sin(v_long);
407     m12 = m23 * m31;
408     m13 = -m22 * m31;
409     m21 = 0.;
410     m32 = -m23 * m11;
411     m33 = m22 * m11;
412 
413     /*
414      *  calc. radius of projected sphere
415      */
416     if (solution == FALSE) {
417 	b_coef = 2 * center_dist * dir_z;
418 	radius_proj =
419 	    (int) sqrt(b_coef * b_coef / (4 * c_coef) - dir_z * dir_z) + 1;
420     }
421 
422     if (fun) {
423 	starty = DIAMETRE / 2 - radius_proj - 3;
424 	endy = DIAMETRE - starty - 1;
425 	if ((double) starty < (double) (-funy))
426 	    starty = -funy;
427 	if ((double) starty > (double) (DIAMETRE - 1 - funy))
428 	    starty = DIAMETRE - 1 - funy;
429 	if ((double) endy < (double) (-funy))
430 	    endy = -funy;
431 	if ((double) endy > (double) (DIAMETRE - 1 - funy))
432 	    endy = DIAMETRE - 1 - funy;
433 
434 	if (solution == FALSE) {
435 	    int i, j;
436 	    if (starty + funy > 0)
437 		for (j = 0; j < starty + funy; j++)
438 		    for (i = 0; i < DIAMETRE; i++)
439 			tabsolu[i][j] = 0;
440 	    if (endy + 1 + funy <= DIAMETRE - 1)
441 		for (j = endy + funy + 1; j < DIAMETRE; j++)
442 		    for (i = 0; i < DIAMETRE; i++)
443 			tabsolu[i][j] = 0;
444 	}
445 
446 	for (py = starty; py <= endy; py++) {
447 
448 	    startx = DIAMETRE / 2 - 6 -
449 		(int) sqrt(MAX((radius_proj * radius_proj -
450 				(py - DIAMETRE / 2) *
451 				(py - DIAMETRE / 2)), 0.0));
452 
453 	    endx = DIAMETRE - startx - 1;
454 	    if ((double) startx < (double) (-funx))
455 		startx = -funx;
456 
457 	    if ((double) startx > (double) (DIAMETRE - 1 - funx))
458 		startx = DIAMETRE - 1 - funx;
459 
460 	    if ((double) endx < (double) (-funx))
461 		endx = -funx;
462 	    if ((double) endx > (double) (DIAMETRE - 1 - funx))
463 		endx = DIAMETRE - 1 - funx;
464 
465 	    if (solution == FALSE) {
466 		int i;
467 		if (startx + funx > 0)
468 		    for (i = 0; i < startx + funx; i++)
469 			tabsolu[i][py + funy] = 0;
470 		if (endx + 1 + funx <= DIAMETRE - 1)
471 		    for (i = endx + 1 + funx; i < DIAMETRE; i++)
472 			tabsolu[i][py + funy] = 0;
473 	    }
474 
475 
476 	    /*
477 	     *  calculate offset into image data
478 	     */
479 
480 	    for (px = startx; px <= endx; px++) {
481 		if (solution == FALSE) {
482 		    dir_x = (double) px - DIAMETRE / 2 + 0.5;
483 		    dir_y = -(double) py + DIAMETRE / 2 - 0.5;
484 
485 		    a = dir_x * dir_x + dir_y * dir_y + dir_z * dir_z;
486 
487 		    udroot = b_coef * b_coef - 4 * a * c_coef;	/*what's under the
488 								   sq.root when solving the                                                                        quadratic equation */
489 		    if (udroot >= 0) {
490 			tabsolu[px + funx][py + funy] = 1;
491 			wurzel = sqrt(udroot);
492 			s1 = (-b_coef + wurzel) / (2. * a);
493 			s2 = (-b_coef - wurzel) / (2. * a);
494 			s = (s1 < s2) ? s1 : s2;	/* smaller solution belongs
495 							   to nearer intersection */
496 			solu[px + funx][py + funy][0] = s * dir_x;
497 			solu[px + funx][py + funy][1] = s * dir_y;
498 			solu[px + funx][py + funy][2] =
499 			    center_dist + s * dir_z;
500 		    } else {
501 			tabsolu[px + funx][py + funy] = 0;
502 		    }
503 		}
504 
505 		if (tabsolu[px + funx][py + funy]) {	/*  solution exists <=>
506 							   intersection exists */
507 		    sp_x = solu[px + funx][py + funy][0];	/* sp = camera pos + s*dir */
508 		    sp_y = solu[px + funx][py + funy][1];
509 		    sp_z = solu[px + funx][py + funy][2];
510 
511 		    hit_x = m11 * sp_x + m12 * sp_y + m13 * sp_z;
512 		    hit_y = m22 * sp_y + m23 * sp_z;
513 		    hit_z = m31 * sp_x + m32 * sp_y + m33 * sp_z;
514 
515 		    hit2_x = -m11 * sp_x + m12 * sp_y + m13 * sp_z;
516 		    hit2_y = m22 * sp_y + m23 * sp_z;
517 		    hit2_z = -m31 * sp_x + m32 * sp_y + m33 * sp_z;
518 /*** hope hit_z wont get too close to zero *******/
519 		    if (ABS(hit_z) < 0.001) {
520 			if (hit_x * hit_z > 0.)
521 			    longitude = PI / 2.;
522 			else
523 			    longitude = -PI / 2.;
524 			if (hit_z > 0.)
525 			    hit_z = 0.001;
526 			else
527 			    hit_z = -0.001;
528 		    } else {
529 			longitude = atan(hit_x / hit_z);
530 		    }
531 
532 		    if (hit_z < 0.)
533 			longitude += PI;
534 
535 		    r = (double) sqrt(hit_x * hit_x + hit_z * hit_z);
536 
537 		    latitude = atan(-hit_y / r);
538 
539 		    light_angle =
540 			(light_x * hit_x + light_y * hit_y +
541 			 light_z * hit_z) / radius;
542 
543 		    /*
544 		     *  Set pixel in image
545 		     */
546 
547 		    teinte =
548 			mygetMapColorLinear(longitude, latitude,
549 					    light_angle);
550 			/* here dont use myRPutPixel since we prefer some
551 			error detection about limits */
552 		    RPutPixel(small, px + funx, py + funy, &teinte);
553 		}
554 	    }			/*px */
555 	}			/*py */
556 
557     }
558 
559 
560 /*** not fun : ***/
561     else {
562 	starty = DIAMETRE / 2 - radius_proj - 3;
563 	starty = (starty < 0) ? 0 : starty;
564 	endy = DIAMETRE - starty - 1;
565 /*
566  * py  0 to 63 max
567  */
568 	if (solution == FALSE) {
569 	    int i, j;
570 	    if (starty > 0)
571 		for (j = 0; j < starty; j++)
572 		    for (i = 0; i < DIAMETRE; i++)
573 			tabsolu[i][j] = 0;
574 	    if (endy + 1 <= DIAMETRE - 1)
575 		for (j = endy + 1; j < DIAMETRE; j++)
576 		    for (i = 0; i < DIAMETRE; i++)
577 			tabsolu[i][j] = 0;
578 	}
579 
580 
581 	for (py = starty; py <= endy; py++) {
582 	    startx = DIAMETRE / 2 - 6 -
583 		(int) sqrt(MAX((radius_proj * radius_proj -
584 				(py - DIAMETRE / 2) *
585 				(py - DIAMETRE / 2)), 0.0));
586 	    startx = (startx < 0) ? 0 : startx;
587 /*
588  *   0<= startx <=31
589  */
590 	    if (solution == FALSE) {
591 		int i;
592 		if (startx > 0)
593 		    for (i = 0; i < startx; i++) {
594 			tabsolu[i][py] = 0;
595 			tabsolu[DIAMETRE - 1 - i][py] = 0;
596 		    }
597 	    }
598 
599 	    for (px = startx; px < DIAMETRE / 2; px++) {
600 		if (solution == FALSE) {
601 		    dir_x = (double) px - DIAMETRE / 2 + 0.5;
602 
603 		    dir_y = -(double) py + DIAMETRE / 2 - 0.5;
604 
605 		    a = dir_x * dir_x + dir_y * dir_y + dir_z * dir_z;
606 
607 		    /*what's under the sq.root when solving the
608 		       quadratic equation */
609 		    udroot = b_coef * b_coef - 4 * a * c_coef;
610 		    if (udroot >= 0) {
611 			tabsolu[px][py] = 1;
612 			tabsolu[DIAMETRE - 1 - px][py] = 1;
613 			wurzel = sqrt(udroot);
614 			s1 = (-b_coef + wurzel) / (2. * a);
615 			s2 = (-b_coef - wurzel) / (2. * a);
616 			s = (s1 < s2) ? s1 : s2;	/* smaller solution
617 							   belongs to nearer
618 							   intersection */
619 			/* sp = camera pos + s*dir */
620 			solu[px][py][0] = s * dir_x;
621 			solu[px][py][1] = s * dir_y;
622 			solu[px][py][2] = center_dist + s * dir_z;
623 		    } else {
624 			tabsolu[px][py] = 0;
625 			tabsolu[DIAMETRE - 1 - px][py] = 0;
626 		    }
627 		}
628 		if (tabsolu[px][py]) {	/*  solution exists <=>
629 					   intersection exists */
630 		    sp_x = solu[px][py][0];
631 		    sp_y = solu[px][py][1];
632 		    sp_z = solu[px][py][2];
633 		    hit_x = m11 * sp_x + m12 * sp_y + m13 * sp_z;
634 		    hit_y = m22 * sp_y + m23 * sp_z;
635 		    hit_z = m31 * sp_x + m32 * sp_y + m33 * sp_z;
636 
637 		    hit2_x = -m11 * sp_x + m12 * sp_y + m13 * sp_z;
638 		    hit2_y = m22 * sp_y + m23 * sp_z;
639 		    hit2_z = -m31 * sp_x + m32 * sp_y + m33 * sp_z;
640 
641 /*** hope hit_z wont get too close to zero *******/
642 #ifdef DEBUG
643 		    if (ABS(hit_z) < ABS(minhz)) {
644 			minhz = hit_z;
645 			fprintf(stdout, "should >>0 : hit_z %f\n", hit_z);
646 			fprintf(stdout, "             hit_x %f\n", hit_x);
647 			fprintf(stdout, "             ratio %f\n",
648 				hit_x / hit_z);
649 			fprintf(stdout, "             long  %f\n",
650 				atan(hit_x / hit_z));
651 
652 			sleep(1);
653 		    }
654 #endif
655 		    if (ABS(hit_z) < 0.001) {
656 			if (hit_x * hit_z > 0.)
657 			    longitude = PI / 2.;
658 			else
659 			    longitude = -PI / 2.;
660 			if (hit_z > 0.)
661 			    hit_z = 0.001;
662 			else
663 			    hit_z = -0.001;
664 		    } else {
665 			longitude = atan(hit_x / hit_z);
666 		    }
667 
668 		    if (hit_z < 0.)
669 			longitude += PI;
670 
671 		    r = (double) sqrt(hit_x * hit_x + hit_z * hit_z);
672 
673 		    latitude = atan(-hit_y / r);
674 
675 		    light_angle =
676 			(light_x * hit_x + light_y * hit_y +
677 			 light_z * hit_z) / radius;
678 		    if (sens == 1) {
679 
680 			/*
681 			 *  Set pixel in image
682 			 */
683 
684 			teinte =
685 			    mygetMapColorLinear(longitude, latitude,
686 						light_angle);
687 			myRPutPixel(px, py, &teinte);
688 
689 			/*
690 			 * mirror the left half-circle of the globe:
691 			 * we need a new position and have to recalc. the
692 			 * light intensity
693 			 */
694 
695 			light_angle =
696 			    (light_x * hit2_x + light_y * hit2_y +
697 			     light_z * hit2_z) / radius;
698 			teinte =
699 			    mygetMapColorLinear(2 * v_long - longitude,
700 						latitude, light_angle);
701 			myRPutPixel(DIAMETRE - px - 1, py, &teinte);
702 		    } else {
703 			/* sens==-1 */
704 			/*
705 			 *  Set pixel in image
706 			 */
707 
708 			teinte =
709 			    mygetMapColorLinear(longitude, latitude,
710 						light_angle);
711 			myRPutPixel(DIAMETRE - px - 1, DIAMETRE - py - 1,
712 				    &teinte);
713 
714 			/*
715 			 * mirror the left half-circle of the globe:
716 			 * we need a new position and have
717 			 * to recalc. the light intensity
718 			 */
719 
720 			light_angle =
721 			    (light_x * hit2_x + light_y * hit2_y +
722 			     light_z * hit2_z) / radius;
723 			teinte =
724 			    mygetMapColorLinear(2 * v_long - longitude,
725 						latitude, light_angle);
726 			myRPutPixel(px, DIAMETRE - py - 1, &teinte);
727 		    }
728 		}
729 	    }			/*px */
730 	}			/*py */
731 
732 
733     }				/*else fun */
734 #if WITH_MARKERS
735 /* markers */
736     if (nb_marker) {
737 	int i;
738 	double mx, my, mz;
739 
740 	for (i = 0; i < nb_marker; i++) {
741 
742 	    mx = m11 * marker[i][0] + m31 * marker[i][2];
743 	    mz = -m31 * marker[i][0] + m11 * marker[i][2];
744 	    my = m22 * marker[i][1] - m23 * mz;
745 	    mz = m23 * marker[i][1] + m22 * mz;
746 
747 	    if (mz > 0) {
748 		if (i == sun_marker) {
749 		    put_dot_cross((int)
750 				  (mx * radius_proj + DIAMETRE / 2 + funx),
751 				  (int) (-my * radius_proj + DIAMETRE / 2 +
752 					 funy), &sun_col);
753 		} else if (i == moon_marker) {
754 		    put_dot_cross((int)
755 				  (mx * radius_proj + DIAMETRE / 2 + funx),
756 				  (int) (-my * radius_proj + DIAMETRE / 2 +
757 					 funy), &moon_col);
758 		} else {
759 		    put_cross((int)
760 			      (mx * radius_proj + DIAMETRE / 2 + funx),
761 			      (int) (-my * radius_proj + DIAMETRE / 2 +
762 				     funy));
763 		}
764 	    }
765 	}
766     }
767 #endif
768     solution = TRUE;
769     return;
770 }
771 
772 
773 
774 
775 
776 
777 
778 
779 
780 
781 
782 
783 
784 static RColor
mygetMapColorLinear(double longitude,double latitude,double angle)785 mygetMapColorLinear(double longitude, double latitude, double angle)
786 {
787     RColor point;
788     int x, y, xl, yl, dx, dy, ang;
789 
790     if (longitude < 0.)
791 	longitude += 2 * PI;
792 
793     latitude += PI / 2;
794 
795     longitude += PI;
796     if (longitude >= 2 * PI)
797 	longitude -= 2 * PI;
798 
799     if (angle > 0)
800 	ang = (int) floor((1 - ((1 - angle) * dawn)) * 256);
801     else
802 	ang = angle * 256;
803 
804     xl = (int) (longitude * mratiox);
805     yl = (int) (latitude * mratioy);
806 
807     x = xl >> 8;
808     y = yl >> 8;
809     dx = xl - (x << 8);
810     dy = yl - (y << 8);
811 
812     if (use_nightmap) {
813 	if (ang > 0) {
814 	    getquarter(map, x, y, md, dx, dy);
815 	    getquarter(mapnight, x, y, mn, dx, dy);
816 
817 	    md[0]->r = ((mn[0]->r * (256 - ang) + md[0]->r * ang)) >> 8;
818 	    md[0]->g = ((mn[0]->g * (256 - ang) + md[0]->g * ang)) >> 8;
819 	    md[0]->b = ((mn[0]->b * (256 - ang) + md[0]->b * ang)) >> 8;
820 	} else {
821 	    getquarter(mapnight, x, y, md, dx, dy);
822 	}
823     } else {
824 	getquarter(map, x, y, md, dx, dy);
825 	if (ang > 0) {
826 	    md[0]->r =
827 		((md[0]->r * aml +
828 		  md[0]->r * ang / 256 * (256 - aml))) >> 8;
829 	    md[0]->g =
830 		((md[0]->g * aml +
831 		  md[0]->g * ang / 256 * (256 - aml))) >> 8;
832 	    md[0]->b =
833 		((md[0]->b * aml +
834 		  md[0]->b * ang / 256 * (256 - aml))) >> 8;
835 	} else {
836 	    md[0]->r = (md[0]->r * aml) >> 8;
837 	    md[0]->g = (md[0]->g * aml) >> 8;
838 	    md[0]->b = (md[0]->b * aml) >> 8;
839 	}
840     }
841 
842     point.red = (unsigned char) md[0]->r;
843     point.green = (unsigned char) md[0]->g;
844     point.blue = (unsigned char) md[0]->b;
845     point.alpha = 255; /* in fun mode, we use original Rputpixel that need alpha?*/
846     return point;
847 }
848 
849 
850 
851 
852 
853 
854 
randomPosition()855 static void randomPosition()
856 {
857     addlat = ((rand() % 30001) / 30000.) * 180. - 90.;
858     addlong = ((rand() % 30001) / 30000.) * 360. - 180.;
859     return;
860 }
861 
862 
863 
864 
865 
866 
867 
868 
869 
updateTime(int force)870 static void updateTime(int force)
871 {
872 /* calcul of sun position every minute */
873     if ((trend.tv_sec - tsunpos) >= 60 || force) {
874 	tsunpos = trend.tv_sec;
875 	sun_position(tsunpos, &sun_lat, &sun_long);
876 	light_x = cos(sun_lat) * sin(sun_long);
877 	light_y = sin(sun_lat);
878 	light_z = cos(sun_lat) * cos(sun_long);
879 	do_something = TRUE;
880 #if WITH_MARKERS
881 	if (sun_marker >= 0) {
882 	    marker[sun_marker][0] = light_x;
883 	    marker[sun_marker][1] = light_y;
884 	    marker[sun_marker][2] = light_z;
885 	}
886 /* ... and the moon position */
887 	if (moon_marker >= 0 || p_type == PTMOON || force == STRONG) {
888 	    moon_position(tsunpos, &moon_lat, &moon_long);
889 	    if (moon_marker >= 0) {
890 		marker[moon_marker][1] = moon_lat;
891 		marker[moon_marker][0] = moon_long;
892 		transform_marker(moon_marker);
893 	    }
894 	}
895 #endif
896     }
897     return;
898 }
899 
900 
901 
902 
903 
904 
905 
906 
907 
transform_marker(int m)908 void transform_marker(int m)
909 {
910     /* long/lat => rotation matrix */
911     double dtmp1, dtmp2;
912 
913     dtmp1 = sin(marker[m][0]) * cos(marker[m][1]);
914     dtmp2 = sin(marker[m][1]);
915     marker[m][2] = cos(marker[m][0]) * cos(marker[m][1]);
916     marker[m][0] = dtmp1;
917     marker[m][1] = dtmp2;
918 }
919 
920 
921 
922 
923 
924 
925 
926 
setViewPos(double lat,double lon)927 void setViewPos(double lat, double lon)
928 {
929     double dif;
930     while (lat >= 360.)
931 	lat -= 360.;
932     while (lat <= -360.)
933 	lat += 360.;
934     while (addlat >= 360.)
935 	addlat -= 360.;
936     while (addlat <= -360.)
937 	addlat += 360.;
938 
939     if (lat >= 90.) {
940 	dif = lat;
941 	lat = 180. - lat;
942 	addlat += (lat - dif);
943 	dlat *= -1;
944 	if (!fun && !stable) {
945 	    lon += 180.;
946 	    addlong += 180.;
947 	}
948 	if (!stable)
949 	    sens *= -1;
950     }
951     if (lat <= -90.) {
952 	dif = lat;
953 	lat = -180. - lat;
954 	addlat += (lat - dif);
955 	dlat *= -1;
956 	if (!fun && !stable) {
957 	    lon += 180.;
958 	    addlong += 180.;
959 	}
960 	if (!stable)
961 	    sens *= -1;
962     }
963     if (lat >= 90.) {
964 	dif = lat;
965 	lat = 180. - lat;
966 	addlat += (lat - dif);
967 	dlat *= -1;
968 	if (!fun && !stable) {
969 	    lon += 180.;
970 	    addlong += 180.;
971 	}
972 	if (!stable)
973 	    sens *= -1;
974     }
975     if (lat <= -90.) {
976 	dif = lat;
977 	lat = -180. - lat;
978 	addlat += (lat - dif);
979 	dlat *= -1;
980 	if (!fun && !stable) {
981 	    lon += 180.;
982 	    addlong += 180.;
983 	}
984 	if (!stable)
985 	    sens *= -1;
986     }
987     while (lon >= 180.) {
988 	lon -= 360.;
989 	addlong -= 360.;
990     }
991     while (lon <= -180.) {
992 	lon += 360.;
993 	addlong += 360.;
994     }
995 
996     v_lat = lat * PI / 180.;
997     v_long = lon * PI / 180.;
998     dv_lat = lat;
999     dv_long = lon;
1000 
1001     return;
1002 }
1003 
1004 
1005 
1006 
1007 
1008 
1009 
1010 
recalc(int force)1011 void recalc(int force)
1012 {
1013     double coeff, va, vo;
1014     struct timeval tv, tnow;
1015 
1016     tnow = getimev();
1017     trend = timeaccel(tnow);
1018     tv = diftimev(tnow, tlast);
1019 
1020     if (firstTime) {
1021 	firstTime = FALSE;
1022 	updateTime(STRONG);
1023     } else {
1024 	coeff = (double) tv.tv_sec + tv.tv_usec / 1000000.;
1025 
1026 	if (!force) {
1027 /** while !clic button rotate earth **/
1028 	    addlat += dlat * coeff;
1029 	    addlong += dlong * coeff;
1030 	}
1031     }
1032 
1033     if (addlong != old_dvlong || addlat != old_dvlat || p_type == PTRANDOM) {
1034 	old_dvlong = addlong;
1035 	old_dvlat = addlat;
1036 	do_something = TRUE;
1037     }
1038 #if WITH_MARKERS
1039     if (force) {
1040 	if (p_type == PTSUN) {
1041 	    va = sun_lat * 180. / PI;
1042 	    vo = sun_long * 180. / PI;
1043 	    updateTime(TRUE);
1044 	    addlat -= sun_lat * 180. / PI - va;
1045 	    addlong -= sun_long * 180. / PI - vo;
1046 	} else if (p_type == PTMOON) {
1047 	    va = moon_lat * 180. / PI;
1048 	    vo = moon_long * 180. / PI;
1049 	    updateTime(TRUE);
1050 	    addlat -= moon_lat * 180. / PI - va;
1051 	    addlong -= moon_long * 180. / PI - vo;
1052 	}
1053 #else
1054     if (force && p_type == PTSUN) {
1055 	va = sun_lat * 180. / PI;
1056 	vo = sun_long * 180. / PI;
1057 	updateTime(TRUE);
1058 	addlat -= sun_lat * 180. / PI - va;
1059 	addlong -= sun_long * 180. / PI - vo;
1060 #endif
1061     } else {
1062 	updateTime(FALSE);
1063     }
1064 
1065     if (do_something) {
1066 	switch (p_type) {
1067 	case PTSUN:
1068 	    setViewPos(sun_lat * 180. / PI + addlat,
1069 		       sun_long * 180. / PI + addlong);
1070 	    break;
1071 
1072 #if WITH_MARKERS
1073 	case PTMOON:
1074 	    setViewPos(moon_lat * 180. / PI + addlat,
1075 		       moon_long * 180. / PI + addlong);
1076 	    break;
1077 #endif
1078 	case PTFIXED:
1079 	    setViewPos(addlat, addlong);
1080 	    break;
1081 
1082 	case PTRANDOM:
1083 	    if (stoprand == FALSE)
1084 		randomPosition();
1085 	    else
1086 		stoprand--;
1087 	    setViewPos(addlat, addlong);
1088 	    break;
1089 
1090 	default:
1091 	    break;
1092 	}
1093 #ifdef DEBUG
1094 	fprintf(stdout, "%s  render\n", ctime(&trend.tv_sec));
1095 #endif
1096 	renderFrame();
1097     }
1098     tlast = tnow;
1099     tnext = addtimev(tnow, tdelay);
1100 
1101     return;
1102 }
1103 
1104 
1105 
1106 
1107 
1108 
1109 /* convert a 4 layers RGBA image to a 3 layer one */
1110 int ripalpha(RImage * image)
1111 {
1112     int x, y;
1113     unsigned char *d, *s, *old;
1114 
1115     if (image == NULL)
1116 	return 0;
1117     if (image->format == RRGBFormat)
1118 	return 1;
1119 
1120     d = malloc(image->width * image->height * 3 + 4);
1121     if (!d) {
1122 	RErrorCode = RERR_NOMEMORY;
1123 	puts("error in ripalpha");
1124 	return 0;
1125     }
1126 
1127     s = image->data;
1128     old = image->data;
1129     image->data = d;
1130     image->format = RRGBFormat;
1131     for (y = 0; y < image->height; y++) {
1132 	for (x = 0; x < image->width; x++) {
1133 	    *d++ = *s++;
1134 	    *d++ = *s++;
1135 	    *d++ = *s++;
1136 	    s++;
1137 	}
1138     }
1139     free(old);
1140     return 1;
1141 }
1142