PDA

View Full Version : GLU Tesselation problem



JernejL
15-12-2006, 01:58 PM
I've created this very simple tesselator of convex polyons into concave ones using GLU, but it crashes if i remove the last showmessage line.. any ideas why?!?!?!?!?!?!?!?!



unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Buttons, opengl;

type

DVector = packed record
x, y, z: double;
end;

TForm1 = class(TForm)
BitBtn1: TBitBtn;
output: TMemo;
procedure BitBtn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

const
GLU_TESS_VERTEX_DATA = 100107;

implementation

{$R *.DFM}

procedure TForm1.BitBtn1Click(Sender: TObject);
var
tess: GLUtesselator;

procedure tessError(errno : GLEnum); stdcall;
begin
showmessage('error, ERROR!');
end;

procedure ElementBegin (mode: GLenum); stdcall;
begin
unit1.Form1.output.lines.add('BEGIN ' + inttostr(mode));
end;

procedure ElementEnd; stdcall;
begin
unit1.Form1.output.lines.add('END');
end;

procedure ElementPrimitiveV2(vertexData : Pointer; polygonData : Pointer); stdcall;
var
pv: DVector;
begin

move(vertexData^, pv, sizeof(dvector));

unit1.Form1.
output.lines.add(
format('%f %f %f', [
pv.x,
pv.y,
pv.z])
);

end;
{
procedure ElementPrimitive(vertexData : Pointer); stdcall;
begin

end;
}
var
poly: array of DVector;
i: integer;
begin
tess:= gluNewTess;

gluTessCallback(tess, GLU_TESS_BEGIN, @ElementBegin);
//gluTessCallback(tess, GLU_TESS_VERTEX, @ElementPrimitive); // directly to opengl...
gluTessCallback(tess, GLU_TESS_VERTEX_DATA, @ElementPrimitiveV2);
gluTessCallback(tess, GLU_TESS_END, @ElementEnd);
gluTessCallback(tess, GLU_TESS_ERROR, @tessError);

gluTessBeginPolygon(tess);
gluTessBeginContour(tess);

setlength(poly, 4);
poly[0].x:= 0;
poly[0].y:= 0;
poly[0].z:= 0;

poly[1].x:= 1;
poly[1].y:= 0;
poly[1].z:= 0;

poly[2].x:= 1;
poly[2].y:= 1;
poly[2].z:= 0;

poly[3].x:= 0;
poly[3].y:= 1;
poly[3].z:= 0;


for i:= 0 to high(poly) do begin
gluTessVertex(tess, @poly[i].x, @poly[i].x);
end;

gluTessEndContour(tess);
gluTessEndPolygon(tess);

gluDeleteTess(tess);

application.processmessages;

showmessage(output.lines.gettext); // UNCOMMENT ME = CRASH.

end;

end.

cronodragon
15-12-2006, 02:45 PM
In my programs I have found those misterious errors which are solved switching 2 lines of code :? Sometimes the compiler does weird things.

But it could also be memory corruption in your code that doesn't crash until that line is removed... try debugging with MemProof, I found Delphi's debugger is not enough to catch every problem. Also Fast Memory Manager could help you better if it's a matter of memory corruption. :)

JernejL
15-12-2006, 03:00 PM
i have no idea what it is, i remove that and the program disappears crashing in totally silence, if i run with delphi's debugger it tells me weird AV error message on addresses way beyond application's range..

tpascal
15-12-2006, 05:50 PM
It happens to me one or two times; I think this is related to a bad pointer access or bad stack memory access.

In your case i think the problem is you are defining everithing in a local stack procedure ( TForm1.BitBtn1Click ), probably including the showmessage procedure makes the compiler build the stack size in a way that hide the problem.

I have not idea how much the variable Tess grow in size but most likely it is passing the stack size; try to move the variable tess: GLUtesselator as global, up after the Form1: TForm1;


good luck.

JernejL
15-12-2006, 06:21 PM
It happens to me one or two times; I think this is related to a bad pointer access or bad stack memory access.

In your case i think the problem is you are defining everithing in a local stack procedure ( TForm1.BitBtn1Click ), probably including the showmessage procedure makes the compiler build the stack size in a way that hide the problem.

I have not idea how much the variable Tess grow in size but most likely it is passing the stack size; try to move the variable tess: GLUtesselator as global, up after the Form1: TForm1;


good luck.

i tried making all procedures global, same effect, also tess does not grow at all.. it is just a identifier / pointer, variable poly however grows, to 96 bytes only.. and i allocated much more data in local procedures.

Setharian
15-12-2006, 06:22 PM
maybe because you're using nested procedures as callbacks? I think it's disallowed, you bypass the compiler by putting "@" in front of the function...probably the stack gets corrupted and you're only lucky it gets executed ok with that last line present.....if it's not the case, then only disassembly could give you a hint on what's wrong....

JSoftware
15-12-2006, 06:22 PM
my gluTessBeginPolygon looks like this:
procedure gluTessBeginPolygon( tess: GLUtesselator; gon_data: Pointer ); stdcall;

JernejL
15-12-2006, 07:14 PM
my gluTessBeginPolygon looks like this:
procedure gluTessBeginPolygon( tess: GLUtesselator; gon_data: Pointer ); stdcall;

you use that definition if you use GLU_TESS_BEGIN_DATA, GLU_TESS_BEGIN is different.

JSoftware
15-12-2006, 07:21 PM
my gluTessBeginPolygon looks like this:
procedure gluTessBeginPolygon( tess: GLUtesselator; gon_data: Pointer ); stdcall;

you use that definition if you use GLU_TESS_BEGIN_DATA, GLU_TESS_BEGIN is different.

Well that doesn't make much sense to me. All I know is that your code compiles for me using the abovementioned calling convention passing nil to gon_data and it works fine.

Would stdcall make your call pass too few parameters on the stack?

JernejL
15-12-2006, 07:44 PM
I don't know what you did, please post the code, it crashes for me if i use your function definition (AND remove the last showmessage line).

edit: are you by any chance using different glu.dll?

JSoftware
15-12-2006, 07:56 PM
You have the code already. It only varies on this line:
gluTessBeginPolygon(tess,nil);

if i import the procedure without the second parameter it'll give me an accessviolation.

glu32.dll you mean? i'm using ver 5.1.2600.2180 from microsoft. The one that came with sp2

edit: try yourself www.graesdal.dk/Project3.zip

JernejL
15-12-2006, 10:30 PM
omg, you are right! must be the bug-ridden and outdated delphi 4 opengl header i used :D :D works perfectly now!

JSoftware
15-12-2006, 10:49 PM
I'm surprised too mine actually works, as i just copied the one supplied with delphi 5 :)

JernejL
15-12-2006, 11:21 PM
Cool, it works perfectly now, i also implemented callback for adding new vertices, so self intresecting polygons work now! (tested! ) so make use of this code as much as you need, i'm posting this so that google bots find it and if anybody has problems with this it is here to help ;)



unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Buttons, opengl;

type

DVector = packed record
x, y, z: double;
end;

PDVector = ^DVector;

Tweight = array[0..3] of single;
Tvertexdata = array[0..3] of longword;

TForm1 = class(TForm)
BitBtn1: TBitBtn;
output: TMemo;
procedure BitBtn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
poly: array of DVector;

const
GLU_TESS_VERTEX_DATA = 100107;
GLU_TESS_BEGIN_DATA = 100106;
GLU_TESS_EDGE_FLAG_DATA = 100110;
GLU_TESS_COMBINE_DATA = 100111;

procedure gluTessBeginPolygon( tess: GLUtesselator; gon_data: Pointer ); stdcall; external glu32;

implementation

{$R *.DFM}

procedure TForm1.BitBtn1Click(Sender: TObject);
var
tess: GLUtesselator;
i: integer;

procedure tessError(errno : GLEnum); stdcall;
begin
showmessage('error, ERROR! ' + inttostr(errno));
end;

procedure ElementBegin (mode: GLenum); stdcall;
begin
unit1.Form1.output.lines.add('BEGIN ' + inttostr(mode));
end;

procedure ElementEnd; stdcall;
begin
unit1.Form1.output.lines.add('END');
end;

Procedure PrimitiveCombine (coords: PDVector; vertex_data: pointer; weight: pointer; var outData: pointer; UserData: Pointer); stdcall;
begin
setlength(poly, length(poly)+1);
move(coords^, poly[length(poly)-1].x, sizeof(dvector));
outData:= @poly[length(poly)-1].x;
end;

Procedure EdgeFlagNull(flag: glboolean; lpContext: pointer); stdcall;
begin

end;

procedure ElementPrimitiveV2(vertexData : Pointer; polygonData : Pointer); stdcall;
var
pv: DVector;
begin

move(vertexData^, pv, sizeof(dvector));

unit1.Form1.
output.lines.add(
format('%f %f %f', [
pv.x,
pv.y,
pv.z])
);

end;

begin
tess:= gluNewTess;

gluTessCallback(tess, GLU_TESS_BEGIN, @ElementBegin);
gluTessCallback(tess, GLU_TESS_VERTEX_DATA, @ElementPrimitiveV2);
//gluTessCallback(tess, GLU_TESS_EDGE_FLAG_DATA, @EdgeFlagNull); // uncomment and you'll get only GL_TRIANGLES!
gluTessCallback(tess, GLU_TESS_COMBINE_DATA, @PrimitiveCombine);
gluTessCallback(tess, GLU_TESS_END, @ElementEnd);
gluTessCallback(tess, GLU_TESS_ERROR, @tessError);

gluTessBeginPolygon(tess, nil);
gluTessBeginContour(tess);

setlength(poly, 4);
poly[0].x:= 0;
poly[0].y:= 0;
poly[0].z:= 0;

poly[1].x:= 1;
poly[1].y:= 0; // set to 1 to test self intresecting polygons
poly[1].z:= 0;

poly[2].x:= 1;
poly[2].y:= 1; // set to 0 to test self intresecting polygons
poly[2].z:= 0;

poly[3].x:= 0;
poly[3].y:= 1;
poly[3].z:= 0;


for i:= 0 to high(poly) do begin
gluTessVertex(tess, @poly[i].x, @poly[i].x);
end;

gluTessEndContour(tess);
gluTessEndPolygon(tess);

gluDeleteTess(tess);

end;

end.