Remove trailing whitespace.
[dockapps.git] / wmglobe / src / rend.c
blobb3b935e0cc498491427c8571283d616897cf03e1
1 /* WMGlobe 1.3 - All the Earth on a WMaker Icon
2 * copyright (C) 1998,99,2000,01 Jerome Dumonteil <jerome.dumonteil@linuxfr.org>
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.
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.
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
21 * This file is part of XGlobe. See README for details.
23 * Copyright (C) 1998 Thorsten Scheuermann
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 ************************************************************************/
30 Some parts of this files should be rewritten to not depend on
31 WindowMaker version
34 #include "wmglobe.h"
36 static RColor mygetMapColorLinear
37 (double longitude, double latitude, double angle);
40 * static RColor getMapColor(double longitude, double latitude, double angle);
43 static void randomPosition();
44 void setViewPos(double lat, double lon);
45 static void myRPutPixel(int x, int y, RColor * color);
46 #ifdef WITH_MARKERS
47 #if (WITH_MARKERS == 1)
48 static void invertPixel(int x, int y);
49 static void put_cross(int x, int y);
50 static void put_dot_cross(int x, int y, RColor * color);
51 #endif
52 #endif
53 static void getquarter(RImage * image, int x, int y, MPO * m[4], int dx,
54 int dy);
55 static void updateTime(int force);
56 static struct timeval timeaccel(struct timeval t);
63 struct timeval timeaccel(struct timeval t)
65 struct timeval at;
66 double rr;
68 t = diftimev(t, tini);
69 rr = floor((double) t.tv_sec * time_multi +
70 (double) t.tv_usec * time_multi / 1000000.);
71 /*** something bad may appen if time_multi=max after 41 minutes (overflow) ***/
72 while (rr > (double) LONG_MAX)
73 rr -= (2.0 * (double) LONG_MAX + 1.0);
74 at.tv_sec = (int) rr;
75 at.tv_usec = (int) (t.tv_usec * time_multi) % 1000000;
76 return addtimev(at, tbase);
84 static void myRPutPixel(int x, int y, RColor * color)
86 int ofs;
87 unsigned char *sr, *sg, *sb;
89 ofs = (y * DIAMETRE + x) * 3;
90 sr = small->data + (ofs++);
91 sg = small->data + (ofs++);
92 sb = small->data + (ofs);
94 *sr = color->red;
95 *sg = color->green;
96 *sb = color->blue;
97 return;
105 #if WITH_MARKERS
106 static void invertPixel(int x, int y)
108 int ofs;
109 unsigned char *sr, *sg, *sb;
111 ofs = (y * DIAMETRE + x) * 3;
112 sr = small->data + (ofs++);
113 sg = small->data + (ofs++);
114 sb = small->data + (ofs);
116 #if ( CROSS_INVERT == 1 )
117 *sr = 255 - *sr;
118 *sg = 255 - *sg;
119 *sb = 255 - *sb;
120 #else
121 if (*sb > 127 || *sg > 127 || *sr > 127)
122 *sr = *sg = *sb = 0;
123 else
124 *sr = *sg = *sb = 255;
125 #endif
126 return;
129 #define T_CADRE(x,y) ((x) < DIAMETRE && (x) >= 0 \
130 && (y) < DIAMETRE && (y) >= 0 && tabsolu[(x)][(y)])
136 static void put_cross(int x, int y)
138 int i, x_cross, y_cross;
140 if (T_CADRE(x, y)) {
141 if (!fun && sens != 1) {
142 x = DIAMETRE - 1 - x;
143 y = DIAMETRE - 1 - y;
145 for (i = 2; i <= CROSS_LENGTH; i++) {
146 x_cross = x + i;
147 y_cross = y;
148 if (T_CADRE(x_cross, y_cross))
149 invertPixel(x_cross, y_cross);
150 x_cross = x - i;
152 if (T_CADRE(x_cross, y_cross))
153 invertPixel(x_cross, y_cross);
154 x_cross = x;
155 y_cross = y - i;
156 if (T_CADRE(x_cross, y_cross))
157 invertPixel(x_cross, y_cross);
159 y_cross = y + i;
160 if (T_CADRE(x_cross, y_cross))
161 invertPixel(x_cross, y_cross);
173 static void put_dot_cross(int x, int y, RColor * color)
175 int i, x_cross, y_cross;
177 if (T_CADRE(x, y)) {
178 if (!fun && sens != 1) {
179 x = DIAMETRE - 1 - x;
180 y = DIAMETRE - 1 - y;
182 for (i = 2; i <= CROSS_LENGTH; i += 2) {
183 x_cross = x + i;
184 y_cross = y;
185 if (T_CADRE(x_cross, y_cross))
186 invertPixel(x_cross, y_cross);
187 x_cross = x - i;
189 if (T_CADRE(x_cross, y_cross))
190 invertPixel(x_cross, y_cross);
191 x_cross = x;
192 y_cross = y - i;
193 if (T_CADRE(x_cross, y_cross))
194 invertPixel(x_cross, y_cross);
196 y_cross = y + i;
197 if (T_CADRE(x_cross, y_cross))
198 invertPixel(x_cross, y_cross);
200 x_cross = x + i + 1;
201 y_cross = y;
202 if (T_CADRE(x_cross, y_cross))
203 myRPutPixel(x_cross, y_cross, color);
204 x_cross = x - i - 1;
206 if (T_CADRE(x_cross, y_cross))
207 myRPutPixel(x_cross, y_cross, color);
208 x_cross = x;
209 y_cross = y - i - 1;
210 if (T_CADRE(x_cross, y_cross))
211 myRPutPixel(x_cross, y_cross, color);
213 y_cross = y + i + 1;
214 if (T_CADRE(x_cross, y_cross))
215 myRPutPixel(x_cross, y_cross, color);
219 #endif
228 static void getquarter(RImage * image, int x, int y, MPO * m[4], int dx,
229 int dy)
231 int xx;
232 register int ofs;
234 /*** hope this is faster than calculation with floats .... ****/
236 x %= image->width;
237 xx = x;
238 y %= image->height;
239 ofs = (y * image->width + x) * 3;
240 m[0]->r = image->data[ofs++];
241 m[0]->g = image->data[ofs++];
242 m[0]->b = image->data[ofs];
244 xx++;
245 xx %= image->width;
246 ofs = (y * image->width + xx) * 3;
247 m[1]->r = image->data[ofs++];
248 m[1]->g = image->data[ofs++];
249 m[1]->b = image->data[ofs];
251 y++;
252 y %= image->height;
253 ofs = (y * image->width + x) * 3;
254 m[2]->r = image->data[ofs++];
255 m[2]->g = image->data[ofs++];
256 m[2]->b = image->data[ofs];
258 ofs = (y * image->width + xx) * 3;
259 m[3]->r = image->data[ofs++];
260 m[3]->g = image->data[ofs++];
261 m[3]->b = image->data[ofs];
265 * m[0]->r=((m[0]->r*(256-dx)*(256-dy))+
266 * (m[1]->r*dx*(256-dy))+
267 * (m[2]->r*(256-dx)*dy)+
268 * (m[3]->r*dx*dy))>>16;
269 * m[0]->g=((m[0]->g*(256-dx)*(256-dy))+
270 * (m[1]->g*dx*(256-dy))+
271 * (m[2]->g*(256-dx)*dy)+
272 * (m[3]->g*dx*dy))>>16;
273 * m[0]->b=((m[0]->b*(256-dx)*(256-dy))+
274 * (m[1]->b*dx*(256-dy))+
275 * (m[2]->b*(256-dx)*dy)+
276 * (m[3]->b*dx*dy))>>16;
279 if ((ofs = m[1]->r - m[0]->r) != 0)
280 m[0]->r += (ofs * dx) >> 8;
281 if ((ofs = m[1]->g - m[0]->g) != 0)
282 m[0]->g += (ofs * dx) >> 8;
283 if ((ofs = m[1]->b - m[0]->b) != 0)
284 m[0]->b += (ofs * dx) >> 8;
286 if ((ofs = m[3]->r - m[2]->r) != 0)
287 m[2]->r += (ofs * dx) >> 8;
288 if ((ofs = m[3]->g - m[2]->g) != 0)
289 m[2]->g += (ofs * dx) >> 8;
290 if ((ofs = m[3]->b - m[2]->b) != 0)
291 m[2]->b += (ofs * dx) >> 8;
293 if ((ofs = m[2]->r - m[0]->r) != 0)
294 m[0]->r += (ofs * dy) >> 8;
295 if ((ofs = m[2]->g - m[0]->g) != 0)
296 m[0]->g += (ofs * dy) >> 8;
297 if ((ofs = m[2]->b - m[0]->b) != 0)
298 m[0]->b += (ofs * dy) >> 8;
300 return;
311 void calcDistance()
313 double tan_a;
315 tan_a = (zoom * DIAMETRE / 2.0) / proj_dist;
317 * distance of camera to center of earth ( = coordinate origin)
319 center_dist = radius / sin(atan(tan_a));
320 c_coef = center_dist * center_dist - radius * radius;
321 solution = FALSE;
322 return;
333 void renderFrame()
335 int py, px;
336 RColor teinte;
338 double dir_x, dir_y, dir_z; /* direction of cast ray */
340 double hit_x, hit_y, hit_z; /* hit position on earth surface */
342 double hit2_x, hit2_y, hit2_z; /* mirrored hit position on earth surface */
344 double sp_x, sp_y, sp_z; /* intersection point of globe and ray */
346 double a; /* coeff. of quardatic equation */
348 double udroot; /* racine */
349 double wurzel;
350 double r; /* r' */
352 double s1, s2, s; /*distance between intersections and
353 camera position */
355 double longitude, latitude; /* coordinates of hit position */
357 double light_angle; /* cosine of angle between sunlight and
358 surface normal */
360 int startx, endx; /* the region to be painted */
362 int starty, endy;
364 double m11;
365 double m12;
366 double m13;
367 double m21;
368 double m22;
369 double m23;
370 double m31;
371 double m32;
372 double m33;
374 a = dir_x = dir_y = 0;
375 dir_z = -proj_dist;
377 #ifdef DEBUG
378 fprintf(stdout, "solution : %d\n", solution);
379 #endif
381 * clear image
383 if (solution == FALSE)
384 RClearImage(small, &noir);
386 * rotation matrix
389 m11 = cos(v_long);
390 m22 = cos(v_lat);
391 m23 = sin(v_lat);
392 m31 = -sin(v_long);
393 m12 = m23 * m31;
394 m13 = -m22 * m31;
395 m21 = 0.;
396 m32 = -m23 * m11;
397 m33 = m22 * m11;
400 * calc. radius of projected sphere
402 if (solution == FALSE) {
403 b_coef = 2 * center_dist * dir_z;
404 radius_proj =
405 (int) sqrt(b_coef * b_coef / (4 * c_coef) - dir_z * dir_z) + 1;
408 if (fun) {
409 starty = DIAMETRE / 2 - radius_proj - 3;
410 endy = DIAMETRE - starty - 1;
411 if ((double) starty < (double) (-funy))
412 starty = -funy;
413 if ((double) starty > (double) (DIAMETRE - 1 - funy))
414 starty = DIAMETRE - 1 - funy;
415 if ((double) endy < (double) (-funy))
416 endy = -funy;
417 if ((double) endy > (double) (DIAMETRE - 1 - funy))
418 endy = DIAMETRE - 1 - funy;
420 if (solution == FALSE) {
421 int i, j;
422 if (starty + funy > 0)
423 for (j = 0; j < starty + funy; j++)
424 for (i = 0; i < DIAMETRE; i++)
425 tabsolu[i][j] = 0;
426 if (endy + 1 + funy <= DIAMETRE - 1)
427 for (j = endy + funy + 1; j < DIAMETRE; j++)
428 for (i = 0; i < DIAMETRE; i++)
429 tabsolu[i][j] = 0;
432 for (py = starty; py <= endy; py++) {
434 startx = DIAMETRE / 2 - 6 -
435 (int) sqrt(MAX((radius_proj * radius_proj -
436 (py - DIAMETRE / 2) *
437 (py - DIAMETRE / 2)), 0.0));
439 endx = DIAMETRE - startx - 1;
440 if ((double) startx < (double) (-funx))
441 startx = -funx;
443 if ((double) startx > (double) (DIAMETRE - 1 - funx))
444 startx = DIAMETRE - 1 - funx;
446 if ((double) endx < (double) (-funx))
447 endx = -funx;
448 if ((double) endx > (double) (DIAMETRE - 1 - funx))
449 endx = DIAMETRE - 1 - funx;
451 if (solution == FALSE) {
452 int i;
453 if (startx + funx > 0)
454 for (i = 0; i < startx + funx; i++)
455 tabsolu[i][py + funy] = 0;
456 if (endx + 1 + funx <= DIAMETRE - 1)
457 for (i = endx + 1 + funx; i < DIAMETRE; i++)
458 tabsolu[i][py + funy] = 0;
463 * calculate offset into image data
466 for (px = startx; px <= endx; px++) {
467 if (solution == FALSE) {
468 dir_x = (double) px - DIAMETRE / 2 + 0.5;
469 dir_y = -(double) py + DIAMETRE / 2 - 0.5;
471 a = dir_x * dir_x + dir_y * dir_y + dir_z * dir_z;
473 udroot = b_coef * b_coef - 4 * a * c_coef; /*what's under the
474 sq.root when solving the quadratic equation */
475 if (udroot >= 0) {
476 tabsolu[px + funx][py + funy] = 1;
477 wurzel = sqrt(udroot);
478 s1 = (-b_coef + wurzel) / (2. * a);
479 s2 = (-b_coef - wurzel) / (2. * a);
480 s = (s1 < s2) ? s1 : s2; /* smaller solution belongs
481 to nearer intersection */
482 solu[px + funx][py + funy][0] = s * dir_x;
483 solu[px + funx][py + funy][1] = s * dir_y;
484 solu[px + funx][py + funy][2] =
485 center_dist + s * dir_z;
486 } else {
487 tabsolu[px + funx][py + funy] = 0;
491 if (tabsolu[px + funx][py + funy]) { /* solution exists <=>
492 intersection exists */
493 sp_x = solu[px + funx][py + funy][0]; /* sp = camera pos + s*dir */
494 sp_y = solu[px + funx][py + funy][1];
495 sp_z = solu[px + funx][py + funy][2];
497 hit_x = m11 * sp_x + m12 * sp_y + m13 * sp_z;
498 hit_y = m22 * sp_y + m23 * sp_z;
499 hit_z = m31 * sp_x + m32 * sp_y + m33 * sp_z;
501 hit2_x = -m11 * sp_x + m12 * sp_y + m13 * sp_z;
502 hit2_y = m22 * sp_y + m23 * sp_z;
503 hit2_z = -m31 * sp_x + m32 * sp_y + m33 * sp_z;
504 /*** hope hit_z wont get too close to zero *******/
505 if (ABS(hit_z) < 0.001) {
506 if (hit_x * hit_z > 0.)
507 longitude = PI / 2.;
508 else
509 longitude = -PI / 2.;
510 if (hit_z > 0.)
511 hit_z = 0.001;
512 else
513 hit_z = -0.001;
514 } else {
515 longitude = atan(hit_x / hit_z);
518 if (hit_z < 0.)
519 longitude += PI;
521 r = (double) sqrt(hit_x * hit_x + hit_z * hit_z);
523 latitude = atan(-hit_y / r);
525 light_angle =
526 (light_x * hit_x + light_y * hit_y +
527 light_z * hit_z) / radius;
530 * Set pixel in image
533 teinte =
534 mygetMapColorLinear(longitude, latitude,
535 light_angle);
536 /* here dont use myRPutPixel since we prefer some
537 error detection about limits */
538 RPutPixel(small, px + funx, py + funy, &teinte);
540 } /*px */
541 } /*py */
546 /*** not fun : ***/
547 else {
548 starty = DIAMETRE / 2 - radius_proj - 3;
549 starty = (starty < 0) ? 0 : starty;
550 endy = DIAMETRE - starty - 1;
552 * py 0 to 63 max
554 if (solution == FALSE) {
555 int i, j;
556 if (starty > 0)
557 for (j = 0; j < starty; j++)
558 for (i = 0; i < DIAMETRE; i++)
559 tabsolu[i][j] = 0;
560 if (endy + 1 <= DIAMETRE - 1)
561 for (j = endy + 1; j < DIAMETRE; j++)
562 for (i = 0; i < DIAMETRE; i++)
563 tabsolu[i][j] = 0;
567 for (py = starty; py <= endy; py++) {
568 startx = DIAMETRE / 2 - 6 -
569 (int) sqrt(MAX((radius_proj * radius_proj -
570 (py - DIAMETRE / 2) *
571 (py - DIAMETRE / 2)), 0.0));
572 startx = (startx < 0) ? 0 : startx;
574 * 0<= startx <=31
576 if (solution == FALSE) {
577 int i;
578 if (startx > 0)
579 for (i = 0; i < startx; i++) {
580 tabsolu[i][py] = 0;
581 tabsolu[DIAMETRE - 1 - i][py] = 0;
585 for (px = startx; px < DIAMETRE / 2; px++) {
586 if (solution == FALSE) {
587 dir_x = (double) px - DIAMETRE / 2 + 0.5;
589 dir_y = -(double) py + DIAMETRE / 2 - 0.5;
591 a = dir_x * dir_x + dir_y * dir_y + dir_z * dir_z;
593 /*what's under the sq.root when solving the
594 quadratic equation */
595 udroot = b_coef * b_coef - 4 * a * c_coef;
596 if (udroot >= 0) {
597 tabsolu[px][py] = 1;
598 tabsolu[DIAMETRE - 1 - px][py] = 1;
599 wurzel = sqrt(udroot);
600 s1 = (-b_coef + wurzel) / (2. * a);
601 s2 = (-b_coef - wurzel) / (2. * a);
602 s = (s1 < s2) ? s1 : s2; /* smaller solution
603 belongs to nearer
604 intersection */
605 /* sp = camera pos + s*dir */
606 solu[px][py][0] = s * dir_x;
607 solu[px][py][1] = s * dir_y;
608 solu[px][py][2] = center_dist + s * dir_z;
609 } else {
610 tabsolu[px][py] = 0;
611 tabsolu[DIAMETRE - 1 - px][py] = 0;
614 if (tabsolu[px][py]) { /* solution exists <=>
615 intersection exists */
616 sp_x = solu[px][py][0];
617 sp_y = solu[px][py][1];
618 sp_z = solu[px][py][2];
619 hit_x = m11 * sp_x + m12 * sp_y + m13 * sp_z;
620 hit_y = m22 * sp_y + m23 * sp_z;
621 hit_z = m31 * sp_x + m32 * sp_y + m33 * sp_z;
623 hit2_x = -m11 * sp_x + m12 * sp_y + m13 * sp_z;
624 hit2_y = m22 * sp_y + m23 * sp_z;
625 hit2_z = -m31 * sp_x + m32 * sp_y + m33 * sp_z;
627 /*** hope hit_z wont get too close to zero *******/
628 #ifdef DEBUG
629 if (ABS(hit_z) < ABS(minhz)) {
630 minhz = hit_z;
631 fprintf(stdout, "should >>0 : hit_z %f\n", hit_z);
632 fprintf(stdout, " hit_x %f\n", hit_x);
633 fprintf(stdout, " ratio %f\n",
634 hit_x / hit_z);
635 fprintf(stdout, " long %f\n",
636 atan(hit_x / hit_z));
638 sleep(1);
640 #endif
641 if (ABS(hit_z) < 0.001) {
642 if (hit_x * hit_z > 0.)
643 longitude = PI / 2.;
644 else
645 longitude = -PI / 2.;
646 if (hit_z > 0.)
647 hit_z = 0.001;
648 else
649 hit_z = -0.001;
650 } else {
651 longitude = atan(hit_x / hit_z);
654 if (hit_z < 0.)
655 longitude += PI;
657 r = (double) sqrt(hit_x * hit_x + hit_z * hit_z);
659 latitude = atan(-hit_y / r);
661 light_angle =
662 (light_x * hit_x + light_y * hit_y +
663 light_z * hit_z) / radius;
664 if (sens == 1) {
667 * Set pixel in image
670 teinte =
671 mygetMapColorLinear(longitude, latitude,
672 light_angle);
673 myRPutPixel(px, py, &teinte);
676 * mirror the left half-circle of the globe:
677 * we need a new position and have to recalc. the
678 * light intensity
681 light_angle =
682 (light_x * hit2_x + light_y * hit2_y +
683 light_z * hit2_z) / radius;
684 teinte =
685 mygetMapColorLinear(2 * v_long - longitude,
686 latitude, light_angle);
687 myRPutPixel(DIAMETRE - px - 1, py, &teinte);
688 } else {
689 /* sens==-1 */
691 * Set pixel in image
694 teinte =
695 mygetMapColorLinear(longitude, latitude,
696 light_angle);
697 myRPutPixel(DIAMETRE - px - 1, DIAMETRE - py - 1,
698 &teinte);
701 * mirror the left half-circle of the globe:
702 * we need a new position and have
703 * to recalc. the light intensity
706 light_angle =
707 (light_x * hit2_x + light_y * hit2_y +
708 light_z * hit2_z) / radius;
709 teinte =
710 mygetMapColorLinear(2 * v_long - longitude,
711 latitude, light_angle);
712 myRPutPixel(px, DIAMETRE - py - 1, &teinte);
715 } /*px */
716 } /*py */
719 } /*else fun */
720 #if WITH_MARKERS
721 /* markers */
722 if (nb_marker) {
723 int i;
724 double mx, my, mz;
726 for (i = 0; i < nb_marker; i++) {
728 mx = m11 * marker[i][0] + m31 * marker[i][2];
729 mz = -m31 * marker[i][0] + m11 * marker[i][2];
730 my = m22 * marker[i][1] - m23 * mz;
731 mz = m23 * marker[i][1] + m22 * mz;
733 if (mz > 0) {
734 if (i == sun_marker) {
735 put_dot_cross((int)
736 (mx * radius_proj + DIAMETRE / 2 + funx),
737 (int) (-my * radius_proj + DIAMETRE / 2 +
738 funy), &sun_col);
739 } else if (i == moon_marker) {
740 put_dot_cross((int)
741 (mx * radius_proj + DIAMETRE / 2 + funx),
742 (int) (-my * radius_proj + DIAMETRE / 2 +
743 funy), &moon_col);
744 } else {
745 put_cross((int)
746 (mx * radius_proj + DIAMETRE / 2 + funx),
747 (int) (-my * radius_proj + DIAMETRE / 2 +
748 funy));
753 #endif
754 solution = TRUE;
755 return;
770 static RColor
771 mygetMapColorLinear(double longitude, double latitude, double angle)
773 RColor point;
774 int x, y, xl, yl, dx, dy, ang;
776 if (longitude < 0.)
777 longitude += 2 * PI;
779 latitude += PI / 2;
781 longitude += PI;
782 if (longitude >= 2 * PI)
783 longitude -= 2 * PI;
785 if (angle > 0)
786 ang = (int) floor((1 - ((1 - angle) * dawn)) * 256);
787 else
788 ang = angle * 256;
790 xl = (int) (longitude * mratiox);
791 yl = (int) (latitude * mratioy);
793 x = xl >> 8;
794 y = yl >> 8;
795 dx = xl - (x << 8);
796 dy = yl - (y << 8);
798 if (use_nightmap) {
799 if (ang > 0) {
800 getquarter(map, x, y, md, dx, dy);
801 getquarter(mapnight, x, y, mn, dx, dy);
803 md[0]->r = ((mn[0]->r * (256 - ang) + md[0]->r * ang)) >> 8;
804 md[0]->g = ((mn[0]->g * (256 - ang) + md[0]->g * ang)) >> 8;
805 md[0]->b = ((mn[0]->b * (256 - ang) + md[0]->b * ang)) >> 8;
806 } else {
807 getquarter(mapnight, x, y, md, dx, dy);
809 } else {
810 getquarter(map, x, y, md, dx, dy);
811 if (ang > 0) {
812 md[0]->r =
813 ((md[0]->r * aml +
814 md[0]->r * ang / 256 * (256 - aml))) >> 8;
815 md[0]->g =
816 ((md[0]->g * aml +
817 md[0]->g * ang / 256 * (256 - aml))) >> 8;
818 md[0]->b =
819 ((md[0]->b * aml +
820 md[0]->b * ang / 256 * (256 - aml))) >> 8;
821 } else {
822 md[0]->r = (md[0]->r * aml) >> 8;
823 md[0]->g = (md[0]->g * aml) >> 8;
824 md[0]->b = (md[0]->b * aml) >> 8;
828 point.red = (unsigned char) md[0]->r;
829 point.green = (unsigned char) md[0]->g;
830 point.blue = (unsigned char) md[0]->b;
831 point.alpha = 255; /* in fun mode, we use original Rputpixel that need alpha?*/
832 return point;
841 static void randomPosition()
843 addlat = ((rand() % 30001) / 30000.) * 180. - 90.;
844 addlong = ((rand() % 30001) / 30000.) * 360. - 180.;
845 return;
856 static void updateTime(int force)
858 /* calcul of sun position every minute */
859 if ((trend.tv_sec - tsunpos) >= 60 || force) {
860 tsunpos = trend.tv_sec;
861 sun_position(tsunpos, &sun_lat, &sun_long);
862 light_x = cos(sun_lat) * sin(sun_long);
863 light_y = sin(sun_lat);
864 light_z = cos(sun_lat) * cos(sun_long);
865 do_something = TRUE;
866 #if WITH_MARKERS
867 if (sun_marker >= 0) {
868 marker[sun_marker][0] = light_x;
869 marker[sun_marker][1] = light_y;
870 marker[sun_marker][2] = light_z;
872 /* ... and the moon position */
873 if (moon_marker >= 0 || p_type == PTMOON || force == STRONG) {
874 moon_position(tsunpos, &moon_lat, &moon_long);
875 if (moon_marker >= 0) {
876 marker[moon_marker][1] = moon_lat;
877 marker[moon_marker][0] = moon_long;
878 transform_marker(moon_marker);
881 #endif
883 return;
894 void transform_marker(int m)
896 /* long/lat => rotation matrix */
897 double dtmp1, dtmp2;
899 dtmp1 = sin(marker[m][0]) * cos(marker[m][1]);
900 dtmp2 = sin(marker[m][1]);
901 marker[m][2] = cos(marker[m][0]) * cos(marker[m][1]);
902 marker[m][0] = dtmp1;
903 marker[m][1] = dtmp2;
913 void setViewPos(double lat, double lon)
915 double dif;
916 while (lat >= 360.)
917 lat -= 360.;
918 while (lat <= -360.)
919 lat += 360.;
920 while (addlat >= 360.)
921 addlat -= 360.;
922 while (addlat <= -360.)
923 addlat += 360.;
925 if (lat >= 90.) {
926 dif = lat;
927 lat = 180. - lat;
928 addlat += (lat - dif);
929 dlat *= -1;
930 if (!fun && !stable) {
931 lon += 180.;
932 addlong += 180.;
934 if (!stable)
935 sens *= -1;
937 if (lat <= -90.) {
938 dif = lat;
939 lat = -180. - lat;
940 addlat += (lat - dif);
941 dlat *= -1;
942 if (!fun && !stable) {
943 lon += 180.;
944 addlong += 180.;
946 if (!stable)
947 sens *= -1;
949 if (lat >= 90.) {
950 dif = lat;
951 lat = 180. - lat;
952 addlat += (lat - dif);
953 dlat *= -1;
954 if (!fun && !stable) {
955 lon += 180.;
956 addlong += 180.;
958 if (!stable)
959 sens *= -1;
961 if (lat <= -90.) {
962 dif = lat;
963 lat = -180. - lat;
964 addlat += (lat - dif);
965 dlat *= -1;
966 if (!fun && !stable) {
967 lon += 180.;
968 addlong += 180.;
970 if (!stable)
971 sens *= -1;
973 while (lon >= 180.) {
974 lon -= 360.;
975 addlong -= 360.;
977 while (lon <= -180.) {
978 lon += 360.;
979 addlong += 360.;
982 v_lat = lat * PI / 180.;
983 v_long = lon * PI / 180.;
984 dv_lat = lat;
985 dv_long = lon;
987 return;
997 void recalc(int force)
999 double coeff, va, vo;
1000 struct timeval tv, tnow;
1002 tnow = getimev();
1003 trend = timeaccel(tnow);
1004 tv = diftimev(tnow, tlast);
1006 if (firstTime) {
1007 firstTime = FALSE;
1008 updateTime(STRONG);
1009 } else {
1010 coeff = (double) tv.tv_sec + tv.tv_usec / 1000000.;
1012 if (!force) {
1013 /** while !clic button rotate earth **/
1014 addlat += dlat * coeff;
1015 addlong += dlong * coeff;
1019 if (addlong != old_dvlong || addlat != old_dvlat || p_type == PTRANDOM) {
1020 old_dvlong = addlong;
1021 old_dvlat = addlat;
1022 do_something = TRUE;
1024 #if WITH_MARKERS
1025 if (force) {
1026 if (p_type == PTSUN) {
1027 va = sun_lat * 180. / PI;
1028 vo = sun_long * 180. / PI;
1029 updateTime(TRUE);
1030 addlat -= sun_lat * 180. / PI - va;
1031 addlong -= sun_long * 180. / PI - vo;
1032 } else if (p_type == PTMOON) {
1033 va = moon_lat * 180. / PI;
1034 vo = moon_long * 180. / PI;
1035 updateTime(TRUE);
1036 addlat -= moon_lat * 180. / PI - va;
1037 addlong -= moon_long * 180. / PI - vo;
1039 #else
1040 if (force && 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 #endif
1047 } else {
1048 updateTime(FALSE);
1051 if (do_something) {
1052 switch (p_type) {
1053 case PTSUN:
1054 setViewPos(sun_lat * 180. / PI + addlat,
1055 sun_long * 180. / PI + addlong);
1056 break;
1058 #if WITH_MARKERS
1059 case PTMOON:
1060 setViewPos(moon_lat * 180. / PI + addlat,
1061 moon_long * 180. / PI + addlong);
1062 break;
1063 #endif
1064 case PTFIXED:
1065 setViewPos(addlat, addlong);
1066 break;
1068 case PTRANDOM:
1069 if (stoprand == FALSE)
1070 randomPosition();
1071 else
1072 stoprand--;
1073 setViewPos(addlat, addlong);
1074 break;
1076 default:
1077 break;
1079 #ifdef DEBUG
1080 fprintf(stdout, "%s render\n", ctime(&trend.tv_sec));
1081 #endif
1082 renderFrame();
1084 tlast = tnow;
1085 tnext = addtimev(tnow, tdelay);
1087 return;
1095 /* convert a 4 layers RGBA image to a 3 layer one */
1096 int ripalpha(RImage * image)
1098 int x, y;
1099 unsigned char *d, *s, *old;
1101 if (image == NULL)
1102 return 0;
1103 if (image->format == RRGBFormat)
1104 return 1;
1106 d = malloc(image->width * image->height * 3 + 4);
1107 if (!d) {
1108 RErrorCode = RERR_NOMEMORY;
1109 puts("error in ripalpha");
1110 return 0;
1113 s = image->data;
1114 old = image->data;
1115 image->data = d;
1116 image->format = RRGBFormat;
1117 for (y = 0; y < image->height; y++) {
1118 for (x = 0; x < image->width; x++) {
1119 *d++ = *s++;
1120 *d++ = *s++;
1121 *d++ = *s++;
1122 s++;
1125 free(old);
1126 return 1;