Dirty Hack in Sphere Mapping: Use int32_t instead of fixed to avoid a dirty error
[kball.git] / src / sphermap.cpp
blobbe8a0faac82876cf2ef875300d4a21a0d96af2d4
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 #warning Dirty Hack: Using int32_t instead of fixed to avoid a dirty error
57 int32_t newx, newy, newz; // x, y and z after rotation
58 fixed z; // z before rotation. we don't have to calculate x and y
60 // calculate z
61 // using pythagoras and the formula for a sphere:
62 // x^2 + y^2 + z^2 = r^2
63 // we know x, y and r
64 z = fixsqrt (r * itofix (r) - x * itofix (x) - y * itofix (y));
66 // apply the rotation matrix to x, y, z.
67 // put the result in newx, newy, newz
68 apply_matrix (rotmat, itofix(x), itofix(y), z, &newx, &newy, &newz);
70 //just as in sphere2.c, we need to check if q_cos is 0
71 //however, q_cos depends on y, and we just calculated a new y
72 //thus we have to calculate q_cos again.
73 newq_cos = fixcos (temp_q) * r;
74 if (newq_cos != 0)
76 // it is possible to use temp_p
77 // temp_p = fixasin (fixdiv (itofix (x), q_cos));
78 // however, I found I get less rounding errors if I use
79 // fixatan2 instead. The principle remains the same.
80 temp_p = fixatan2 (fixdiv (newx, newq_cos), fixdiv (newz, newq_cos));
82 else
83 temp_p = 0;
85 temp_p &= 0xFFFFFF;
87 p = fixtoi (temp_p) * (map->w-1) / 256;
89 // calculate q
90 temp_q = fixasin (newy / r);
91 q = fixtoi (temp_q + itofix (64)) * (map->h-1) / 128;
93 putpixel (target, x + cx, y + cy, getpixel(map, p, q) );