1 /*
2 * Example program for the Allegro library, by Bertrand Coconnier.
3 *
4 * This program demonstrates how to use Z-buffered polygons and
5 * floating point 3D math routines. It also provides a simple
6 * way to compute fps (frames per second) using a timer. After
7 * selecting a screen resolution through the standard GUI dialog,
8 * the example shows two 3D cubes rotating and intersecting each
9 * other. Rather than having full polygons incorrectly overlap
10 * other polygons due to per-polygon sorting, each pixel is drawn
11 * at the correct depth.
12 */
13
14
15 #include <allegro.h>
16
17
18
19 typedef struct FACE
20 {
21 int v1, v2, v3, v4;
22 } FACE;
23
24
25 V3D_f cube1[] =
26 {
27 { -32., -32., -32., 0., 0., 72},
28 { -32., 32., -32., 0., 0., 80},
29 { 32., 32., -32., 0., 0., 95},
30 { 32., -32., -32., 0., 0., 88},
31 { -32., -32., 32., 0., 0., 72},
32 { -32., 32., 32., 0., 0., 80},
33 { 32., 32., 32., 0., 0., 95},
34 { 32., -32., 32., 0., 0., 88}
35 };
36
37
38 V3D_f cube2[] =
39 {
40 { -32., -32., -32., 0., 0., 104},
41 { -32., 32., -32., 0., 0., 112},
42 { 32., 32., -32., 0., 0., 127},
43 { 32., -32., -32., 0., 0., 120},
44 { -32., -32., 32., 0., 0., 104},
45 { -32., 32., 32., 0., 0., 112},
46 { 32., 32., 32., 0., 0., 127},
47 { 32., -32., 32., 0., 0., 120}
48 };
49
50
51 FACE faces[] =
52 {
53 { 2, 1, 0, 3 },
54 { 4, 5, 6, 7 },
55 { 0, 1, 5, 4 },
56 { 2, 3, 7, 6 },
57 { 4, 7, 3, 0 },
58 { 1, 2, 6, 5 }
59 };
60
61
62
63 volatile int t;
64
65
66 /* timer interrupt handler */
tick(void)67 void tick(void)
68 {
69 t++;
70 }
71
END_OF_FUNCTION(tick)72 END_OF_FUNCTION(tick)
73
74
75
76 /* update cube positions */
77 void anim_cube(MATRIX_f* matrix1, MATRIX_f* matrix2, V3D_f x1[], V3D_f x2[])
78 {
79 int i;
80
81 for (i=0; i<8; i++) {
82 apply_matrix_f(matrix1, cube1[i].x, cube1[i].y, cube1[i].z,
83 &(x1[i].x), &(x1[i].y), &(x1[i].z));
84 apply_matrix_f(matrix2, cube2[i].x, cube2[i].y, cube2[i].z,
85 &(x2[i].x), &(x2[i].y), &(x2[i].z));
86 persp_project_f(x1[i].x, x1[i].y, x1[i].z, &(x1[i].x), &(x1[i].y));
87 persp_project_f(x2[i].x, x2[i].y, x2[i].z, &(x2[i].x), &(x2[i].y));
88 }
89 }
90
91
92
93 /* cull backfaces and draw cubes */
draw_cube(BITMAP * buffer,V3D_f x1[],V3D_f x2[])94 void draw_cube(BITMAP* buffer, V3D_f x1[], V3D_f x2[])
95 {
96 int i;
97
98 for (i=0; i<6; i++) {
99 V3D_f vtx1, vtx2, vtx3, vtx4;
100
101 vtx1 = x1[faces[i].v1];
102 vtx2 = x1[faces[i].v2];
103 vtx3 = x1[faces[i].v3];
104 vtx4 = x1[faces[i].v4];
105 if (polygon_z_normal_f(&vtx1, &vtx2, &vtx3) > 0)
106 quad3d_f(buffer, POLYTYPE_GCOL | POLYTYPE_ZBUF, NULL,
107 &vtx1, &vtx2, &vtx3, &vtx4);
108
109 vtx1 = x2[faces[i].v1];
110 vtx2 = x2[faces[i].v2];
111 vtx3 = x2[faces[i].v3];
112 vtx4 = x2[faces[i].v4];
113 if (polygon_z_normal_f(&vtx1, &vtx2, &vtx3) > 0)
114 quad3d_f(buffer, POLYTYPE_GCOL | POLYTYPE_ZBUF, NULL,
115 &vtx1, &vtx2, &vtx3, &vtx4);
116 }
117 }
118
119
120
main(void)121 int main(void)
122 {
123 ZBUFFER *zbuf;
124 BITMAP *buffer;
125 PALETTE pal;
126 MATRIX_f matrix1, matrix2;
127 V3D_f x1[8], x2[8];
128
129 int i;
130 int c = GFX_AUTODETECT;
131 int w, h, bpp;
132
133 int frame = 0;
134 float fps = 0.;
135
136 float rx1, ry1, rz1; /* cube #1 rotations */
137 float drx1, dry1, drz1; /* cube #1 rotation speed */
138 float rx2, ry2, rz2; /* cube #2 rotations */
139 float drx2, dry2, drz2; /* cube #1 rotation speed */
140 float tx = 16.; /* x shift between cubes */
141 float tz1 = 100.; /* cube #1 z coordinate */
142 float tz2 = 105.; /* cube #2 z coordinate */
143
144 if (allegro_init() != 0)
145 return 1;
146 install_keyboard();
147 install_mouse();
148 install_timer();
149
150 LOCK_VARIABLE(t);
151 LOCK_FUNCTION(tick);
152
153 install_int(tick, 10);
154
155 /* color 0 = black */
156 pal[0].r = pal[0].g = pal[0].b = 0;
157 /* color 1 = red */
158 pal[1].r = 255;
159 pal[1].g = pal[1].b = 0;
160
161 /* copy the desktop palette */
162 for (i=1; i<64; i++)
163 pal[i] = desktop_palette[i];
164
165 /* make a blue gradient */
166 for (i=64; i<96; i++) {
167 pal[i].b = (i-64)*2;
168 pal[i].g = pal[i].r = 0;
169 }
170
171 /* make a green gradient */
172 for (i=96; i<128; i++) {
173 pal[i].g = (i-96)*2;
174 pal[i].r = pal[i].b = 0;
175 }
176
177 /* set the graphics mode */
178 if (set_gfx_mode(GFX_SAFE, 320, 200, 0, 0) != 0) {
179 set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
180 allegro_message("Unable to set any graphic mode\n%s\n", allegro_error);
181 return 1;
182 }
183 set_palette(desktop_palette);
184
185 w = SCREEN_W;
186 h = SCREEN_H;
187 bpp = bitmap_color_depth(screen);
188 if (!gfx_mode_select_ex(&c, &w, &h, &bpp)) {
189 allegro_exit();
190 return 1;
191 }
192
193 set_color_depth(bpp);
194
195 if (set_gfx_mode(c, w, h, 0, 0) != 0) {
196 set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
197 allegro_message("Error setting graphics mode\n%s\n", allegro_error);
198 return 1;
199 }
200
201 set_palette_range(pal, 0, 127, FALSE);
202
203 /* double buffer the animation and create the Z-buffer */
204 buffer = create_bitmap(SCREEN_W, SCREEN_H);
205 zbuf = create_zbuffer(buffer);
206 set_zbuffer(zbuf);
207
208 /* set up the viewport for the perspective projection */
209 set_projection_viewport(0, 0, SCREEN_W, SCREEN_H);
210
211 /* compute rotations and speed rotation */
212 rx1 = ry1 = rz1 = 0.;
213 rx2 = ry2 = rz2 = 0.;
214
215 drx1 = ((AL_RAND() & 31) - 16) / 4.;
216 dry1 = ((AL_RAND() & 31) - 16) / 4.;
217 drz1 = ((AL_RAND() & 31) - 16) / 4.;
218
219 drx2 = ((AL_RAND() & 31) - 16) / 4.;
220 dry2 = ((AL_RAND() & 31) - 16) / 4.;
221 drz2 = ((AL_RAND() & 31) - 16) / 4.;
222
223 /* set the transformation matrices */
224 get_transformation_matrix_f(&matrix1, 1., rx1, ry1, rz1, tx, 0., tz1);
225 get_transformation_matrix_f(&matrix2, 1., rx2, ry2, rz2, -tx, 0., tz2);
226
227 /* set colors */
228 for (i=0; i<8; i++) {
229 x1[i].c = palette_color[cube1[i].c];
230 x2[i].c = palette_color[cube2[i].c];
231 }
232
233 /* main loop */
234 while(1) {
235 clear_bitmap(buffer);
236 clear_zbuffer(zbuf, 0.);
237
238 anim_cube(&matrix1, &matrix2, x1, x2);
239 draw_cube(buffer, x1, x2);
240
241 /* update transformation matrices */
242 rx1 += drx1;
243 ry1 += dry1;
244 rz1 += drz1;
245 rx2 += drx2;
246 ry2 += dry2;
247 rz2 += drz2;
248 get_transformation_matrix_f(&matrix1, 1., rx1, ry1, rz1, tx, 0., tz1);
249 get_transformation_matrix_f(&matrix2, 1., rx2, ry2, rz2, -tx, 0., tz2);
250
251 textprintf_ex(buffer, font, 10, 1, palette_color[1], 0,
252 "Z-buffered polygons (%.1f fps)", fps);
253
254 vsync();
255 blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
256 frame++;
257
258 if (t > 100) {
259 fps = (100. * frame) / t;
260 t = 0;
261 frame = 0;
262 }
263
264 if (keypressed()){
265 if ((readkey() & 0xFF) == 27)
266 break;
267 }
268 }
269
270 destroy_bitmap(buffer);
271 destroy_zbuffer(zbuf);
272
273 return 0;
274 }
275
276 END_OF_MAIN()
277