simplistic mouse cursor
[metatoy] / src / gfxutil.c
1 #include <string.h>
2 #include <assert.h>
3 #include "game.h"
4 #include "gfxutil.h"
5 #include "3dgfx/3dgfx.h"
6
7 #if 0
8 enum {
9         IN              = 0,
10         LEFT    = 1,
11         RIGHT   = 2,
12         TOP             = 4,
13         BOTTOM  = 8
14 };
15
16 static int outcode(int x, int y, int xmin, int ymin, int xmax, int ymax)
17 {
18         int code = 0;
19
20         if(x < xmin) {
21                 code |= LEFT;
22         } else if(x > xmax) {
23                 code |= RIGHT;
24         }
25         if(y < ymin) {
26                 code |= TOP;
27         } else if(y > ymax) {
28                 code |= BOTTOM;
29         }
30         return code;
31 }
32
33 #define FIXMUL(a, b)    (((a) * (b)) >> 8)
34 #define FIXDIV(a, b)    (((a) << 8) / (b))
35
36 #define LERP(a, b, t)   ((a) + FIXMUL((b) - (a), (t)))
37
38 int clip_line(int *x0, int *y0, int *x1, int *y1, int xmin, int ymin, int xmax, int ymax)
39 {
40         int oc_out;
41
42         int oc0 = outcode(*x0, *y0, xmin, ymin, xmax, ymax);
43         int oc1 = outcode(*x1, *y1, xmin, ymin, xmax, ymax);
44
45         long fx0, fy0, fx1, fy1, fxmin, fymin, fxmax, fymax;
46
47         if(!(oc0 | oc1)) return 1;      /* both points are inside */
48
49         fx0 = *x0 << 8;
50         fy0 = *y0 << 8;
51         fx1 = *x1 << 8;
52         fy1 = *y1 << 8;
53         fxmin = xmin << 8;
54         fymin = ymin << 8;
55         fxmax = xmax << 8;
56         fymax = ymax << 8;
57
58         for(;;) {
59                 long x, y, t;
60
61                 if(oc0 & oc1) return 0;         /* both have points with the same outbit, not visible */
62                 if(!(oc0 | oc1)) break;         /* both points are inside */
63
64                 oc_out = oc0 ? oc0 : oc1;
65
66                 if(oc_out & TOP) {
67                         t = FIXDIV(fymin - fy0, fy1 - fy0);
68                         x = LERP(fx0, fx1, t);
69                         y = fymin;
70                 } else if(oc_out & BOTTOM) {
71                         t = FIXDIV(fymax - fy0, fy1 - fy0);
72                         x = LERP(fx0, fx1, t);
73                         y = fymax;
74                 } else if(oc_out & LEFT) {
75                         t = FIXDIV(fxmin - fx0, fx1 - fx0);
76                         x = fxmin;
77                         y = LERP(fy0, fy1, t);
78                 } else /*if(oc_out & RIGHT)*/ {
79                         t = FIXDIV(fxmax - fx0, fx1 - fx0);
80                         x = fxmax;
81                         y = LERP(fy0, fy1, t);
82                 }
83
84                 if(oc_out == oc0) {
85                         fx0 = x;
86                         fy0 = y;
87                         oc0 = outcode(fx0 >> 8, fy0 >> 8, xmin, ymin, xmax, ymax);
88                 } else {
89                         fx1 = x;
90                         fy1 = y;
91                         oc1 = outcode(fx1 >> 8, fy1 >> 8, xmin, ymin, xmax, ymax);
92                 }
93         }
94
95         *x0 = fx0 >> 8;
96         *y0 = fy0 >> 8;
97         *x1 = fx1 >> 8;
98         *y1 = fy1 >> 8;
99         return 1;
100 }
101
102 void draw_line(int x0, int y0, int x1, int y1, unsigned char color)
103 {
104         int i, dx, dy, x_inc, y_inc, error;
105         unsigned char *fb = framebuf;
106
107         fb += y0 * FB_WIDTH + x0;
108
109         dx = x1 - x0;
110         dy = y1 - y0;
111
112         if(dx >= 0) {
113                 x_inc = 1;
114         } else {
115                 x_inc = -1;
116                 dx = -dx;
117         }
118         if(dy >= 0) {
119                 y_inc = FB_WIDTH;
120         } else {
121                 y_inc = -FB_WIDTH;
122                 dy = -dy;
123         }
124
125         if(dx > dy) {
126                 error = dy * 2 - dx;
127                 for(i=0; i<=dx; i++) {
128                         *fb = color;
129                         if(error >= 0) {
130                                 error -= dx * 2;
131                                 fb += y_inc;
132                         }
133                         error += dy * 2;
134                         fb += x_inc;
135                 }
136         } else {
137                 error = dx * 2 - dy;
138                 for(i=0; i<=dy; i++) {
139                         *fb = color;
140                         if(error >= 0) {
141                                 error -= dy * 2;
142                                 fb += x_inc;
143                         }
144                         error += dx * 2;
145                         fb += y_inc;
146                 }
147         }
148 }
149 #endif
150
151 void draw_billboard(float x, float y, float z, float size, int lum, int a)
152 {
153         float m[16];
154         size *= 0.5f;
155
156         g3d_matrix_mode(G3D_MODELVIEW);
157         g3d_push_matrix();
158
159         g3d_translate(x, y, z);
160
161         g3d_get_matrix(G3D_MODELVIEW, m);
162         /* make the upper 3x3 part of the matrix identity */
163         m[0] = m[5] = m[10] = 1.0f;
164         m[1] = m[2] = m[3] = m[4] = m[6] = m[7] = m[8] = m[9] = 0.0f;
165         g3d_load_matrix(m);
166
167         g3d_begin(G3D_QUADS);
168         g3d_color2b(lum, a);
169         g3d_texcoord(0, 0);
170         g3d_vertex(-size, -size, 0);
171         g3d_texcoord(1, 0);
172         g3d_vertex(size, -size, 0);
173         g3d_texcoord(1, 1);
174         g3d_vertex(size, size, 0);
175         g3d_texcoord(0, 1);
176         g3d_vertex(-size, size, 0);
177         g3d_end();
178
179         g3d_pop_matrix();
180 }