Imported kball_final_src_16dec2004.tar.gz
[kball.git] / src / sphermap.cpp
blob4d14e895f32aec62177404adcc14a7d1400fa701
1 // -----------------------------------------------------------------------
2 // sphermap.cpp
3 // -----------------------------------------------------------------------
4 // Code to render a sphere
5 // From Pixelate #11, article written by Martijn 'amarillion' van Iersel
6 // -----------------------------------------------------------------------
7 // Modified by Kronoman to suit the needs of the game.
8 // -----------------------------------------------------------------------
10 #include <stdio.h>
12 #include "sphermap.h"
15 get_planet_rotation_matrix() is a little helper function to calculate a
16 rotation matrix for a planet. An ordinary rotation matrix doesn't work well
17 for planets.
19 MATRIX *m: pointer to the resulting MATRIX struct
20 fixed rotation: rotation of the planet around its axis of rotation
21 fixed axisx, axisz: rotation around the x and z axes.
23 void get_planet_rotation_matrix (MATRIX *m, fixed rotation, fixed axisx, fixed axisz)
25 MATRIX m1, m2;
26 // apply rotation around y axis first
27 get_y_rotate_matrix (&m1, rotation);
29 // then apply rotation around x and z axes.
30 get_rotation_matrix (&m2, axisx, 0, axisz);
32 matrix_mul (&m2, &m1, m);
36 get_mapped_sphere_ex() is similar to get_mapped_sphere(), but also takes
37 a rotation matrix as argument to draw a rotated sphere.
39 BITMAP *target = bitmap to display onto
40 int cx, cy = center of the sphere
41 int r = radius of the sphere
42 BITMAP *map = bitmap to map onto the sphere
43 MATRIX *rotmat = rotation matrix
45 void mapped_sphere_ex (BITMAP *target, int cx, int cy, int r, BITMAP *map, MATRIX *rotmat)
47 int x, y; // coordinates on the target bitmap
48 int p, q; // coordinates on the source bitmap
50 for (y = -r; y < r; y++)
52 fixed q_cos = fixcos (- fixasin (itofix (y) / r)) * r;
53 for (x = - fixtoi (q_cos) + 1; x < fixtoi(q_cos) - 1; x++)
55 fixed newq_cos, temp_p, temp_q=0; // some temporary variables
56 fixed newx, newy, newz; // x, y and z after rotation
57 fixed z; // z before rotation. we don't have to calculate x and y
59 // calculate z
60 // using pythagoras and the formula for a sphere:
61 // x^2 + y^2 + z^2 = r^2
62 // we know x, y and r
63 z = fixsqrt (r * itofix (r) - x * itofix (x) - y * itofix (y));
65 // apply the rotation matrix to x, y, z.
66 // put the result in newx, newy, newz
67 apply_matrix (rotmat, itofix(x), itofix(y), z, &newx, &newy, &newz);
69 //just as in sphere2.c, we need to check if q_cos is 0
70 //however, q_cos depends on y, and we just calculated a new y
71 //thus we have to calculate q_cos again.
72 newq_cos = fixcos (temp_q) * r;
73 if (newq_cos != 0)
75 // it is possible to use temp_p
76 // temp_p = fixasin (fixdiv (itofix (x), q_cos));
77 // however, I found I get less rounding errors if I use
78 // fixatan2 instead. The principle remains the same.
79 temp_p = fixatan2 (fixdiv (newx, newq_cos), fixdiv (newz, newq_cos));
81 else
82 temp_p = 0;
84 temp_p &= 0xFFFFFF;
86 p = fixtoi (temp_p) * (map->w-1) / 256;
88 // calculate q
89 temp_q = fixasin (newy / r);
90 q = fixtoi (temp_q + itofix (64)) * (map->h-1) / 128;
92 putpixel (target, x + cx, y + cy, getpixel(map, p, q) );