Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » Allegro 4.4 RC2 - polygon3d

This thread is locked; no one can reply to it. rss feed Print
Allegro 4.4 RC2 - polygon3d
Niunio
Member #1,975
March 2002
avatar

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.

-----------------
Current projects: Allegro.pas | MinGRo

GullRaDriel
Member #3,861
September 2003
avatar

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"
Allegro Wiki, full of examples and articles !!

Thomas Fjellstrom
Member #476
June 2000
avatar

I don't think it can be a real allegro bug if you can't reproduce it in C.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Niunio
Member #1,975
March 2002
avatar

[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:

#SelectExpand
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. ???

-----------------
Current projects: Allegro.pas | MinGRo

GullRaDriel
Member #3,861
September 2003
avatar

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"
Allegro Wiki, full of examples and articles !!

gnolam
Member #2,030
March 2002
avatar

That code has an array overrun.

Niunio said:
V3D_f Vertex[2], VertexR[2];

[...]

    Vertex[2].x =  1;

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

GullRaDriel
Member #3,861
September 2003
avatar

ouch ^^

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

Niunio
Member #1,975
March 2002
avatar

gnolam said:

That code has an array overrun.

Duh! :-X

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. :-/

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?

-----------------
Current projects: Allegro.pas | MinGRo

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
avatar

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! :o

-----------------
Current projects: Allegro.pas | MinGRo

Thomas Fjellstrom
Member #476
June 2000
avatar

If it uses a CPU exception to handle the conversion, yeah it'll break anything ;)

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Niunio
Member #1,975
March 2002
avatar

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. :D

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?

-----------------
Current projects: Allegro.pas | MinGRo

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.

--
"Either help out or stop whining" - Evert

Go to: