|
Allegro 4.4 RC2 - polygon3d |
Niunio
Member #1,975
March 2002
|
This is the possible bug I was talking the last months. May be it only affects to Pascal because I can't reproduce it in C. The problem is "polygon3d" generates a segmentation fault when rendering textured 3D polygons with "POLYTYPE_PTEX" modifier when the polygon is (almost) perpendicular to the screen plane. After some tests I did find it fails with angles <188, 74, 188>, <196, 53, 128>, <31, 62, 188> and its equivalents (<1212, 330, 1212>, <193, 53, 384>, etc). The attached file is the simplest test program I used (included the wrapper units needed). Just change the initial angle values to reproduce the error faster. You can compile it with Free Pascal (included in several Linux distros). To compile, from the same directory, just execute "fpc -g test" ("-g" generates debug information). Of course you need Allegro installed. ----------------- |
GullRaDriel
Member #3,861
September 2003
|
I will perhaps give it a go this evening, but no promise Niunio. "Code is like shit - it only smells if it is not yours" |
Thomas Fjellstrom
Member #476
June 2000
|
I don't think it can be a real allegro bug if you can't reproduce it in C. -- |
Niunio
Member #1,975
March 2002
|
[edit] I've updated the attached file on the first message because I find an error in one of the loops. Anyway, it fails the same way[/edit] I tried to reproduce it in C, so I translate my test program to C: 1/* Testing 3D polygons. */
2
3#include <allegro.h>
4#include <stdio.h>
5#include <stdlib.h>
6
7
8 BITMAP *Texture, *BackBuffer;
9
10
11
12/* Creates a texture to be used by the cube. */
13 void CreateTexture (void)
14 {
15 int Black, White, Green;
16
17 Black = makecol (0, 0, 0);
18 White = makecol (255, 255, 255);
19 Green = makecol (0, 255, 0);
20 if (!(Texture = create_bitmap (32, 32)))
21 puts ("Can't create texture.");
22 clear_to_color (Texture, Black);
23 line (Texture, 0, 0, 31, 31, White);
24 line (Texture, 0, 32, 32, 0, White);
25 rect (Texture, 0, 0, 31, 31, White);
26 textout_ex (Texture, font, "dead", 0, 0, Green, -1);
27 textout_ex (Texture, font, "pigs", 0, 8, Green, -1);
28 textout_ex (Texture, font, "cant", 0, 16, Green, -1);
29 textout_ex (Texture, font, "fly.", 0, 24, Green, -1);
30 }
31
32
33
34/* This procedure tests the polygon. */
35 void DoTest (int aMode)
36 {
37 V3D_f Vertex[2], VertexR[2];
38 float Ax, Ay, Az,
39 Rx, Ry, Rz;
40 int Vtx;
41 MATRIX_f Matrix;
42
43 /* Vertex. */
44 Vertex[0].x = 0;
45 Vertex[1].x = -1;
46 Vertex[2].x = 1;
47 Vertex[0].y = 1;
48 Vertex[1].y = 0;
49 Vertex[2].y = 0;
50 Vertex[0].z = 0;
51 Vertex[1].z = 0;
52 Vertex[2].z = 0;
53 /* Texture mapping. */
54 Vertex[0].u = 15;
55 Vertex[1].u = 0;
56 Vertex[2].u = 31;
57 Vertex[0].v = 0;
58 Vertex[1].v = 31;
59 Vertex[2].v = 31;
60 for (Vtx=0; Vtx<3; ++Vtx) {
61 VertexR[Vtx].u = Vertex[Vtx].u;
62 VertexR[Vtx].v = Vertex[Vtx].v;
63 }
64 /* Angles. */
65 Ax = 0;
66 Ay = 0;
67 Az = 0;
68 Rx = (float)((rand () % 32) - 16) / 8;
69 Ry = (float)((rand () % 32) - 16) / 8;
70 Rz = (float)((rand () % 32) - 16) / 8;
71 /* Testing. */
72 do {
73 /* Animation. */
74 Ax += Rx;
75 Ay += Ry;
76 Az += Rz;
77printf ("<%d, %d, %d>\n", (int)Ax, (int)Ay, (int)Az);
78 get_transformation_matrix_f (&Matrix, 1, Ax, Ay, Az, 0, 0, -3);
79 for (Vtx=0; Vtx<3; ++Vtx) {
80 apply_matrix_f (&Matrix,
81 Vertex [Vtx].x, Vertex [Vtx].y, Vertex [Vtx].z,
82 &(VertexR[Vtx].x), &(VertexR[Vtx].y), &(VertexR[Vtx].z));
83 persp_project_f (VertexR[Vtx].x, VertexR[Vtx].y, VertexR[Vtx].z,
84 &(VertexR[Vtx].x), &(VertexR[Vtx].y));
85 }
86 /* Output. */
87 clear_bitmap (BackBuffer);
88 textout_centre_ex (BackBuffer, font,
89 aMode == POLYTYPE_ATEX ? "POLYTYPE_ATEX" : "POLYTYPE_PTEX",
90 160, 1, makecol (255, 255, 255), -1);
91 triangle3d_f (BackBuffer, aMode, Texture, &(VertexR[0]), &(VertexR[1]), &(VertexR[2]));
92 vsync;
93 blit (BackBuffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
94 } while (!keypressed ());
95 readkey (); /* Clear buffer. */
96 }
97
98
99
100int main (void) /* The program starts here. */
101{
102/* You should always do this at the start of Allegro programs. */
103 if (allegro_init () != 0) {
104 puts ("Can't initialize Allegro!");
105 return EXIT_FAILURE;
106 }
107 install_keyboard ();
108 install_timer ();
109
110/* Set a graphics mode sized 320x200. */
111 if (set_gfx_mode (GFX_AUTODETECT_WINDOWED, 320, 200, 0, 0) != 0)
112 if (set_gfx_mode (GFX_SAFE, 320, 200, 0, 0) != 0) {
113 set_gfx_mode (GFX_TEXT, 0, 0, 0, 0);
114 /* Show an error message. */
115 allegro_message ("Error setting graphics mode");
116 allegro_exit ();
117 return EXIT_FAILURE;
118 }
119 BackBuffer = create_bitmap (SCREEN_W, SCREEN_H);
120 CreateTexture ();
121 set_projection_viewport (0, 0, SCREEN_W, SCREEN_H);
122
123 DoTest (POLYTYPE_ATEX);
124 DoTest (POLYTYPE_PTEX);
125
126 destroy_bitmap (BackBuffer);
127 destroy_bitmap (Texture);
128 allegro_exit ();
129 return EXIT_SUCCESS;
130}
131
132END_OF_MAIN ();
I think it's a perfect translation of the Pascal program, but I don't know why it's so chaotic. ----------------- |
GullRaDriel
Member #3,861
September 2003
|
And so, is the bug also visible in C with your chaotic (;-)) test program ? "Code is like shit - it only smells if it is not yours" |
gnolam
Member #2,030
March 2002
|
-- |
GullRaDriel
Member #3,861
September 2003
|
ouch ^^ "Code is like shit - it only smells if it is not yours" |
Niunio
Member #1,975
March 2002
|
gnolam said: That code has an array overrun. Duh! GullRaDriel said: And so, is the bug also visible in C with your chaotic (;-)) test program ? Once fixed the problem gnolam pointed to it seems to work. Thomas Fjellstrom said: I don't think it can be a real allegro bug if you can't reproduce it in C. I'm not sure. If you use Allegro.pas with Allegro 4.4.0 RC1 there is a similar problem with rotate_sprite, and previously with fixed-point maths, but there are no problems with RC2 and I didn't change my code. May be there's a calling convention issue or something? ----------------- |
Peter Wang
Member #23
April 2000
|
I can reproduce the crash in the pascal version. It doesn't crash under valgrind though, nor does valgrind flag anything strange. EDIT: fpc is probably enabling overflow detection in float->int conversion. The problem is in cscan.h (FUNC_POLY_SCANLINE_PTEX): for (x = w - 1; x >= 0; x -= 4) { long nextu, nextv, du, dv; PIXEL_PTR s; unsigned long color; fu += dfu; fv += dfv; fz += dfz; nextu = fu * z1; // here nextv = fv * z1; // here // ...snip... } If I change nextu, nextv to int64_t instead of long, the SIGFPE goes away. Next question is if this is the correct fix.
|
Niunio
Member #1,975
March 2002
|
Peter Wang said: fpc is probably enabling overflow detection in float->int conversion. The problem is in cscan.h (FUNC_POLY_SCANLINE_PTEX): for (x = w - 1; x >= 0; x -= 4) { long nextu, nextv, du, dv; PIXEL_PTR s; unsigned long color; fu += dfu; fv += dfv; fz += dfz; nextu = fu * z1; // here nextv = fv * z1; // here // ...snip... } If I change nextu, nextv to int64_t instead of long, the SIGFPE goes away. Next question is if this is the correct fix. I confirm this change fixes the problem. Thanks for the tip, Peter. Pascal is very strict about data typing, but I didn't know that "strictness" affects also to libraries written and compiled in other languages! ----------------- |
Thomas Fjellstrom
Member #476
June 2000
|
If it uses a CPU exception to handle the conversion, yeah it'll break anything -- |
Niunio
Member #1,975
March 2002
|
A small update: I was testing the fix suggested by Peter. It seems to work but should be applied in more functions. I did changed it in all the ones that uses similar code in cscan.h file and now all examples works. Thomas Fjellstrom said: If it uses a CPU exception to handle the conversion, yeah it'll break anything Didn't know about CPU exception. That explains a lot. Thanks. So, next release will have this change, will not? ----------------- |
Elias
Member #358
May 2000
|
int64_t looks like a better choice than long here - it's in general only very rare situations where you would want to use long instead of int64_t. But when that code originally was written most likely we didn't have the fixed-width types yet. -- |
|