Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [quad3d] Crash!

This thread is locked; no one can reply to it. rss feed Print
[quad3d] Crash!
ngiacomelli
Member #5,114
October 2004

I noticed that my game was crashing with a call to quad3d. This happens randomly, so I initially suspected overflow, or something similarly nasty and subversive! Basically, on my menu screen, the player can rotate a cube to select what he or she wants to do (New Game, Exit, etc).

I logged some of the values that my game was passing to quad3d:

Here's the call:
quad3d(b, POLYTYPE_PTEX, nav_texture[face], &vtx1, &vtx2, &vtx3, &vtx4);

Here's the type of numbers you see when the program doesn't crash:

 vtx1: 8642240 6481680 11927552
 vtx2: 8642240 9246960 11927552
 vtx3: 12329280 9246960 11927552
 vtx4: 12329280 6481680 11927552

Here's some from when it does:

 vtx1: 320 120 2097169
 vtx2: 320 15728520 2097169
 vtx3: 20971360 15728520 2097169
 vtx4: 20971360 120 2097169

The entire 3d navigation code is relatively self-contained. It's also part of a game started during a hack, so it's pretty messy:

Header:

1#ifndef nav3d
2#define nav3d
3 
4#define NUM_VERTICES 8
5#define NUM_FACES 6
6 
7typedef struct VTX
8{
9 fixed x, y, z;
10} VTX;
11 
12typedef struct QUAD
13{
14 VTX *vtxlist;
15 int id;
16 int v1, v2, v3, v4;
17} QUAD;
18 
19typedef struct SHAPE
20{
21 fixed x, y, z;
22 fixed rx, ry, rz;
23 fixed dz;
24 fixed drx, dry, drz;
25} SHAPE;
26 
27VTX points[] =
28{
29 { -32 << 16, -32 << 16, -32 << 16 },
30 { -32 << 16, 32 << 16, -32 << 16 },
31 { 32 << 16, 32 << 16, -32 << 16 },
32 { 32 << 16, -32 << 16, -32 << 16 },
33 { -32 << 16, -32 << 16, 32 << 16 },
34 { -32 << 16, 32 << 16, 32 << 16 },
35 { 32 << 16, 32 << 16, 32 << 16 },
36 { 32 << 16, -32 << 16, 32 << 16 },
37};
38 
39QUAD faces[] =
40{
41 { points, 0, 0, 3, 2, 1 },
42 { points, 1, 4, 5, 6, 7 },
43 { points, 2, 0, 1, 5, 4 },
44 { points, 3, 2, 3, 7, 6 },
45 { points, 4, 0, 4, 7, 3 },
46 { points, 5, 1, 2, 6, 5 }
47};
48 
49SHAPE nav_cube;
50VTX output_points[NUM_VERTICES];
51QUAD output_faces[NUM_FACES];
52 
53int mov_count, mov_direction;
54 
55BITMAP *nav_texture[6], *plank;
56char keybuf[KEY_MAX];
57 
58#endif

Here's the code that renders and translates the cube:

1void translate_shapes(void)
2{
3
4 int c, d;
5 MATRIX matrix;
6 VTX *outpoint = output_points;
7 QUAD *outface = output_faces;
8 
9 get_transformation_matrix(&matrix, itofix(1), nav_cube.rx, nav_cube.ry, nav_cube.rz, nav_cube.x, nav_cube.y, nav_cube.z);
10 
11 for (d = 0; d < NUM_VERTICES; d++) {
12 apply_matrix(&matrix, points[d].x, points[d].y, points[d].z,
13 &outpoint[d].x, &outpoint[d].y, &outpoint[d].z);
14 persp_project(outpoint[d].x, outpoint[d].y, outpoint[d].z,
15 &outpoint[d].x, &outpoint[d].y);
16 }
17 
18 for (d=0; d<NUM_FACES; d++) {
19 outface[d] = faces[d];
20 outface[d].vtxlist = outpoint;
21 }
22 
23 outpoint += NUM_VERTICES;
24 outface += NUM_FACES;
25 
26}
27 
28void draw_quad(BITMAP *b, VTX *v1, VTX *v2, VTX *v3, VTX *v4, int face)
29{
30
31 /* four vertices */
32 V3D vtx1 = { 0, 0, 0, 0, 0, 0 };
33 V3D vtx2 = { 0, 0, 0, 32<<16, 0, 0 };
34 V3D vtx3 = { 0, 0, 0, 32<<16, 32<<16, 0 };
35 V3D vtx4 = { 0, 0, 0, 0, 32<<16, 0 };
36 
37 vtx1.x = v1->x; vtx1.y = v1->y; vtx1.z = v1->z;
38 vtx2.x = v2->x; vtx2.y = v2->y; vtx2.z = v2->z;
39 vtx3.x = v3->x; vtx3.y = v3->y; vtx3.z = v3->z;
40 vtx4.x = v4->x; vtx4.y = v4->y; vtx4.z = v4->z;
41 
42 log_write(" vtx1: %i %i %i", vtx1.x, vtx1.y, vtx1.z );
43 log_write(" vtx2: %i %i %i", vtx2.x, vtx2.y, vtx2.z );
44 log_write(" vtx3: %i %i %i", vtx3.x, vtx3.y, vtx3.z );
45 log_write(" vtx4: %i %i %i", vtx4.x, vtx4.y, vtx4.z );
46 
47 quad3d(b, POLYTYPE_PTEX, nav_texture[face], &vtx1, &vtx2, &vtx3, &vtx4); // Crashes here!
48 
49}
50 
51int quad_cmp(const void *e1, const void *e2)
52{
53
54 QUAD *q1 = (QUAD *)e1;
55 QUAD *q2 = (QUAD *)e2;
56 
57 fixed d1 = q1->vtxlist[q1->v1].z + q1->vtxlist[q1->v2].z +
58 q1->vtxlist[q1->v3].z + q1->vtxlist[q1->v4].z;
59 
60 fixed d2 = q2->vtxlist[q2->v1].z + q2->vtxlist[q2->v2].z +
61 q2->vtxlist[q2->v3].z + q2->vtxlist[q2->v4].z;
62 
63 return d2 - d1;
64
65}
66 
67void draw_shapes(BITMAP *b)
68{
69
70 int c;
71 QUAD *face = output_faces;
72 VTX *v1, *v2, *v3, *v4;
73 
74 qsort(output_faces, NUM_FACES, sizeof(QUAD), quad_cmp);
75 
76 for (c=0; c < NUM_FACES; c++) {
77 
78 v1 = face->vtxlist + face->v1;
79 v2 = face->vtxlist + face->v2;
80 v3 = face->vtxlist + face->v3;
81 v4 = face->vtxlist + face->v4;
82 
83 draw_quad(b, v1, v2, v3, v4, face->id);
84 
85 face++;
86
87 }
88
89}

Here's how I set everything up:

1int setup_navigation()
2{
3
4 int i = 0, x = 0, y = 0, i_a = 0;
5
6 nav_cube.x = 0; nav_cube.y = 0; nav_cube.z = 150 << 16;
7 nav_cube.rx = 0; nav_cube.ry = 0; nav_cube.rz = 0;
8 nav_cube.dz = 0; nav_cube.drx = 0; nav_cube.dry = 0; nav_cube.drz = 0;
9
10 mov_count = 0; mov_direction = 0;
11
12 set_projection_viewport(0, 0, 320, 240);
13
14 nav_texture[0] = load_bitmap("gfx/hud/tex0.bmp", NULL);
15 nav_texture[1] = load_bitmap("gfx/hud/tex1.bmp", NULL);
16 nav_texture[2] = load_bitmap("gfx/hud/tex2.bmp", NULL);
17 nav_texture[3] = load_bitmap("gfx/hud/tex3.bmp", NULL);
18 nav_texture[4] = load_bitmap("gfx/hud/tex4.bmp", NULL);
19 nav_texture[5] = load_bitmap("gfx/hud/tex5.bmp", NULL);
20
21 plank = load_bitmap("gfx/hud/plank.bmp", NULL);
22
23 if( nav_texture[0] == NULL || nav_texture[1] == NULL || nav_texture[2] == NULL || nav_texture[3] == NULL ||
24 nav_texture[5] == NULL || plank == NULL ) return 1;
25
26 return 0;
27 
28}

Any suggestions?

kdevil
Member #1,075
March 2001
avatar

v1 = face->vtxlist + face->v1;
v2 = face->vtxlist + face->v2;
v3 = face->vtxlist + face->v3;
v4 = face->vtxlist + face->v4;

The only suggestion I have is to add some logging before those statements and make sure you're getting what you expect for face->vtxlist.

-----
"I am the Black Mage! I casts the spells that makes the peoples fall down!"

Arthur Kalliokoski
Second in Command
February 2005
avatar

The crashing numbers include 320 and 120. Do those particular values occur somewhere else? Just a guess... a wild pointer is stuffing them everywhere

“Throughout history, poverty is the normal condition of man. Advances which permit this norm to be exceeded — here and there, now and then — are the work of an extremely small minority, frequently despised, often condemned, and almost always opposed by all right-thinking people. Whenever this tiny minority is kept from creating, or (as sometimes happens) is driven out of a society, the people then slip back into abject poverty. This is known as "bad luck.”

― Robert A. Heinlein

ngiacomelli
Member #5,114
October 2004

EDIT: Looks like the navigation code is fine. If I skip its execution entirely, the game will still crash at random points. Looks like it's a rogue pointer, or something equally horrible!

EDIT 2: Scratch that. Actually, with the navigation code entirely commented out, I have no crash problems. It's in there, somewhere.

Full header:

#SelectExpand
1#ifndef nav3d 2#define nav3d 3 4#define NUM_VERTICES 8 5#define NUM_FACES 6 6 7typedef struct VTX 8{ 9 fixed x, y, z; 10} VTX; 11 12typedef struct QUAD 13{ 14 VTX *vtxlist; 15 int id; 16 int v1, v2, v3, v4; 17} QUAD; 18 19typedef struct SHAPE 20{ 21 fixed x, y, z; 22 fixed rx, ry, rz; 23 fixed dz; 24 fixed drx, dry, drz; 25} SHAPE; 26 27VTX points[] = 28{ 29 { -32 << 16, -32 << 16, -32 << 16 }, 30 { -32 << 16, 32 << 16, -32 << 16 }, 31 { 32 << 16, 32 << 16, -32 << 16 }, 32 { 32 << 16, -32 << 16, -32 << 16 }, 33 { -32 << 16, -32 << 16, 32 << 16 }, 34 { -32 << 16, 32 << 16, 32 << 16 }, 35 { 32 << 16, 32 << 16, 32 << 16 }, 36 { 32 << 16, -32 << 16, 32 << 16 }, 37}; 38 39QUAD faces[] = 40{ 41 { points, 0, 0, 3, 2, 1 }, 42 { points, 1, 4, 5, 6, 7 }, 43 { points, 2, 0, 1, 5, 4 }, 44 { points, 3, 2, 3, 7, 6 }, 45 { points, 4, 0, 4, 7, 3 }, 46 { points, 5, 1, 2, 6, 5 } 47}; 48 49SHAPE nav_cube; 50VTX output_points[NUM_VERTICES]; 51QUAD output_faces[NUM_FACES]; 52 53int mov_count, mov_direction; 54 55BITMAP *nav_texture[6]; 56BITMAP *plank; 57char keybuf[KEY_MAX]; 58 59#endif

Full source:

#SelectExpand
1#include <allegro.h> 2#include "application.h" 3#include "canvas.h" 4#include "object.h" 5#include "nav3d.h" 6 7void draw_quad(BITMAP *b, VTX *v1, VTX *v2, VTX *v3, VTX *v4, int face); 8 9int setup_navigation() 10{ 11 12 int i = 0, x = 0, y = 0, i_a = 0; 13 14 nav_cube.x = 0; nav_cube.y = 0; nav_cube.z = 150 << 16; 15 nav_cube.rx = 0; nav_cube.ry = 0; nav_cube.rz = 0; 16 nav_cube.dz = 0; nav_cube.drx = 0; nav_cube.dry = 0; nav_cube.drz = 0; 17 18 mov_count = 0; mov_direction = 0; 19 20 set_projection_viewport(0, 0, 320, 240); 21 22 nav_texture[0] = load_bitmap("gfx/hud/tex0.bmp", NULL); 23 nav_texture[1] = load_bitmap("gfx/hud/tex1.bmp", NULL); 24 nav_texture[2] = load_bitmap("gfx/hud/tex2.bmp", NULL); 25 nav_texture[3] = load_bitmap("gfx/hud/tex3.bmp", NULL); 26 nav_texture[4] = load_bitmap("gfx/hud/tex4.bmp", NULL); 27 nav_texture[5] = load_bitmap("gfx/hud/tex5.bmp", NULL); 28 29 plank = load_bitmap("gfx/hud/plank.bmp", NULL); 30 31 if( nav_texture[0] == NULL || nav_texture[1] == NULL || nav_texture[2] == NULL || nav_texture[3] == NULL || 32 nav_texture[5] == NULL || plank == NULL ) return 1; 33 34 return 0; 35 36} 37 38void update_navigation(void) 39{ 40 41 nav_cube.z += nav_cube.dz; 42 43 if ((nav_cube.z > itofix(1024)) || (nav_cube.z < itofix(192))) nav_cube.dz = -nav_cube.dz; 44 45 nav_cube.rx += nav_cube.drx; 46 nav_cube.ry += nav_cube.dry; 47 nav_cube.rz += nav_cube.drz; 48 49} 50 51void translate_shapes(void) 52{ 53 54 int c, d; 55 MATRIX matrix; 56 VTX *outpoint = output_points; 57 QUAD *outface = output_faces; 58 59 get_transformation_matrix(&matrix, itofix(1), nav_cube.rx, nav_cube.ry, nav_cube.rz, nav_cube.x, nav_cube.y, nav_cube.z); 60 61 for (d = 0; d < NUM_VERTICES; d++) { 62 apply_matrix(&matrix, points[d].x, points[d].y, points[d].z, 63 &outpoint[d].x, &outpoint[d].y, &outpoint[d].z); 64 persp_project(outpoint[d].x, outpoint[d].y, outpoint[d].z, 65 &outpoint[d].x, &outpoint[d].y); 66 } 67 68 for (d=0; d<NUM_FACES; d++) { 69 outface[d] = faces[d]; 70 outface[d].vtxlist = outpoint; 71 } 72 73 outpoint += NUM_VERTICES; 74 outface += NUM_FACES; 75 76} 77 78void draw_quad(BITMAP *b, VTX *v1, VTX *v2, VTX *v3, VTX *v4, int face) 79{ 80 81 V3D vtx1 = { 0, 0, 0, 0, 0, 0 }; 82 V3D vtx2 = { 0, 0, 0, 32<<16, 0, 0 }; 83 V3D vtx3 = { 0, 0, 0, 32<<16, 32<<16, 0 }; 84 V3D vtx4 = { 0, 0, 0, 0, 32<<16, 0 }; 85 86 vtx1.x = v1->x; vtx1.y = v1->y; vtx1.z = v1->z; 87 vtx2.x = v2->x; vtx2.y = v2->y; vtx2.z = v2->z; 88 vtx3.x = v3->x; vtx3.y = v3->y; vtx3.z = v3->z; 89 vtx4.x = v4->x; vtx4.y = v4->y; vtx4.z = v4->z; 90 91 log_write(" vtx1: %i %i %i", vtx1.x, vtx1.y, vtx1.z ); 92 log_write(" vtx2: %i %i %i", vtx2.x, vtx2.y, vtx2.z ); 93 log_write(" vtx3: %i %i %i", vtx3.x, vtx3.y, vtx3.z ); 94 log_write(" vtx4: %i %i %i", vtx4.x, vtx4.y, vtx4.z ); 95 96 quad3d(b, POLYTYPE_PTEX, nav_texture[face], &vtx1, &vtx2, &vtx3, &vtx4); // Crashes here! 97 98} 99 100int quad_cmp(const void *e1, const void *e2) 101{ 102 103 QUAD *q1 = (QUAD *)e1; 104 QUAD *q2 = (QUAD *)e2; 105 106 fixed d1 = q1->vtxlist[q1->v1].z + q1->vtxlist[q1->v2].z + 107 q1->vtxlist[q1->v3].z + q1->vtxlist[q1->v4].z; 108 109 fixed d2 = q2->vtxlist[q2->v1].z + q2->vtxlist[q2->v2].z + 110 q2->vtxlist[q2->v3].z + q2->vtxlist[q2->v4].z; 111 112 return d2 - d1; 113 114} 115 116void draw_shapes(BITMAP *b) 117{ 118 119 int c; 120 QUAD *face = output_faces; 121 VTX *v1, *v2, *v3, *v4; 122 qsort(output_faces, NUM_FACES, sizeof(QUAD), quad_cmp); 123 124 for (c=0; c < NUM_FACES; c++) { 125 126 v1 = face->vtxlist + face->v1; 127 v2 = face->vtxlist + face->v2; 128 v3 = face->vtxlist + face->v3; 129 v4 = face->vtxlist + face->v4; 130 131 draw_quad(b, v1, v2, v3, v4, face->id); 132 133 face++; 134 135 } 136 137} 138 139int get_look_face() 140{ 141 142 int c; 143 144 QUAD *face = output_faces; 145 146 qsort(output_faces, NUM_FACES, sizeof(QUAD), quad_cmp); 147 148 for( c = 0; c < NUM_FACES; c++ ) { 149 150 if( c == (NUM_FACES-1) ) return face->id; 151 face++; 152 153 } 154 155 return -1; 156 157} 158 159void menu_logic() { 160 161 update_navigation(); 162 translate_shapes(); 163 164 if( mov_count > 0 ) { 165 166 mov_count += 2; 167 168 switch( mov_direction ) { 169 170 case 0: 171 nav_cube.rx += itofix(2); 172 break; 173 case 1: 174 nav_cube.rx -= itofix(2); 175 break; 176 case 2: 177 nav_cube.ry -= itofix(2); 178 break; 179 case 3: 180 nav_cube.ry += itofix(2); 181 break; 182 183 } 184 185 if( mov_count > 64 ) { 186 mov_count = 0; 187 } 188 189 } 190 191} 192 193void menu_input() { 194 195 if( key[KEY_D] && !keybuf[KEY_D] && mov_count <= 0 ) { 196 197 mov_count = 1; mov_direction = 3; 198 199 } 200 201 if( key[KEY_A] && !keybuf[KEY_A] && mov_count <= 0 ) { 202 203 mov_count = 1; mov_direction = 2; 204 205 } 206 207 if( key[KEY_S] && !keybuf[KEY_S] && mov_count <= 0 ) { 208 209 mov_count = 1; mov_direction = 0; 210 211 } 212 213 if( key[KEY_W] && !keybuf[KEY_W] && mov_count <= 0 ) { 214 215 mov_count = 1; mov_direction = 1; 216 217 } 218 219 if( key[KEY_SPACE] && !keybuf[KEY_SPACE] && mov_count <= 0 ) { 220 221 switch( get_look_face() ) { 222 223 case 0: 224 application_set_state(APP_GAME); 225 break; 226 case 1: 227 application_set_state(APP_TERMINATING); 228 break; 229 230 } 231 232 } 233 234 memcpy((void*)keybuf,(void*)key,sizeof(keybuf)); 235 236} 237 238void render_menu() 239{ 240 241 int x = 0, y = 0; 242 243 clear_to_color( buffer, makecol( 0, 0, 0 ) ); 244 245 draw_shapes( buffer ); 246 draw_sprite( buffer, plank, 110, 168 ); 247 248 if( mov_count <= 0 ) { 249 250 switch( get_look_face() ) { 251 252 case 0: 253 textprintf_centre_ex(buffer, small_n, 160, 181, makecol(0, 0, 0), -1, "NEW GAME"); 254 textprintf_centre_ex(buffer, small_n, 160, 180, makecol(255, 255, 255), -1, "NEW GAME"); 255 break; 256 case 1: 257 textprintf_centre_ex(buffer, small_n, 160, 181, makecol(0, 0, 0), -1, "EXIT"); 258 textprintf_centre_ex(buffer, small_n, 160, 180, makecol(255, 255, 255), -1, "EXIT"); 259 break; 260 case 2: 261 textprintf_centre_ex(buffer, small_n, 160, 181, makecol(0, 0, 0), -1, "CREDITS"); 262 textprintf_centre_ex(buffer, small_n, 160, 180, makecol(255, 255, 255), -1, "CREDITS"); 263 break; 264 case 3: 265 textprintf_centre_ex(buffer, small_n, 160, 181, makecol(0, 0, 0), -1, "OPTIONS"); 266 textprintf_centre_ex(buffer, small_n, 160, 180, makecol(255, 255, 255), -1, "OPTIONS"); 267 break; 268 case 4: 269 textprintf_centre_ex(buffer, small_n, 160, 181, makecol(0, 0, 0), -1, "LOAD GAME"); 270 textprintf_centre_ex(buffer, small_n, 160, 180, makecol(255, 255, 255), -1, "LOAD GAME"); 271 break; 272 case 5: 273 textprintf_centre_ex(buffer, small_n, 160, 181, makecol(0, 0, 0), -1, "SAVE GAME"); 274 textprintf_centre_ex(buffer, small_n, 160, 180, makecol(255, 255, 255), -1, "SAVE GAME"); 275 break; 276 277 } 278 279 } 280 281 stretch_blit(buffer, screen, 0, 0, 320, 240, 0, 0, 640, 480); 282 283}

kazzmir
Member #1,786
December 2001
avatar

Would you mind attaching the source to the entire project? Im willing to debug it but I dont want to hack together the source from your code pastes.

Go to: