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