123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- //
- // The graphics engine GLXEngine. The unit of GLScene for Delphi
- //
- unit GLS.PolygonTesselation;
- (* Code to generate triangle strips and fans for polygons *)
- interface
- {$I Stage.Defines.inc}
- uses
- Winapi.OpenGL,
- System.SysUtils,
- GLS.OpenGLAdapter,
- Stage.OpenGLTokens,
- Stage.VectorTypes,
- GLS.VectorLists,
- Stage.VectorGeometry,
- GLS.VectorFileObjects,
- GLS.PersistentClasses;
- (* Tesselates the polygon outlined by the Vertexes. And adds them to the first
- facegroup of the Mesh. *)
- procedure DoTesselate(Vertexes: TGLAffineVectorList; Mesh: TGLBaseMesh;
- normal: PAffineVector = nil; invertNormals: Boolean = False);
- //---------------------------------------------------------------------------
- implementation
- //---------------------------------------------------------------------------
- {$IFDEF USE_MULTITHREAD}
- threadvar
- {$ELSE}
- var
- {$ENDIF}
- TessMesh: TGLMeshObject;
- TessFace: TFGIndexTexCoordList;
- TessVerticesCount, TessExtraVertices: Integer;
- TessVertices: PAffineVectorArray;
- procedure DoTessBegin(mode: Cardinal);
- {$IFDEF MSWINDOWS} stdcall;{$ELSE} cdecl;{$ENDIF}
- begin
- TessFace := TFGIndexTexCoordList.CreateOwned(TessMesh.FaceGroups);
- case mode of
- GL_TRIANGLES: TessFace.Mode := fgmmTriangles;
- GL_TRIANGLE_STRIP: TessFace.Mode := fgmmTriangleStrip;
- GL_TRIANGLE_FAN: TessFace.Mode := fgmmTriangleFan;
- end;
- end;
- procedure DoTessVertex3fv(v: PAffineVector);
- {$IFDEF MSWINDOWS} stdcall;{$ELSE} cdecl;{$ENDIF}
- begin
- TessFace.Add(TessMesh.Vertices.Add(v^), 0, 0);
- end;
- procedure DoTessEnd;
- {$IFDEF MSWINDOWS} stdcall;{$ELSE} cdecl;{$ENDIF}
- begin
- end;
- procedure DoTessError(errno: Cardinal);
- {$IFDEF MSWINDOWS} stdcall;{$ELSE} cdecl;{$ENDIF}
- begin
- Assert(False, IntToStr(errno) + ': ' + string(gluErrorString(errno)));
- end;
- function AllocNewVertex: PAffineVector;
- begin
- Inc(TessExtraVertices);
- // Allocate more memory if needed
- if TessExtraVertices > TessVerticesCount then
- begin
- TessVerticesCount := TessVerticesCount * 2;
- Reallocmem(TessVertices, TessVerticesCount * SizeOf(TAffineVector));
- end;
- Result := @TessVertices[TessExtraVertices - 1];
- end;
- procedure DoTessCombine(coords: PDoubleVector; vertex_data: Pointer; weight: PGLFloat; var outData: Pointer);
- {$IFDEF MSWINDOWS} stdcall;{$ELSE} cdecl;{$ENDIF}
- begin
- outData := AllocNewVertex;
- SetVector(PAffineVector(outData)^, coords[0], coords[1], coords[2]);
- end;
- procedure DoTesselate(Vertexes: TGLAffineVectorList; Mesh: TGLBaseMesh; normal: PAffineVector = nil; invertNormals: Boolean = False);
- var
- Tess: PGLUTesselator;
- i: Integer;
- dblVector: TAffineDblVector;
- begin
- // Select or Create FaceGroup
- if Mesh.MeshObjects.Count = 0 then
- begin
- TessMesh := TGLMeshObject.CreateOwned(Mesh.MeshObjects);
- Mesh.MeshObjects[0].Mode := momFaceGroups;
- end
- else
- TessMesh := Mesh.MeshObjects[0];
- // vertices count.
- TessVerticesCount := Vertexes.Count;
- // allocate extra buffer used by GLU in complex polygons.
- GetMem(TessVertices, TessVerticesCount * SizeOf(TAffineVector));
- // make a Tessellation GLU object.
- Tess := gluNewTess;
- // set up callback events
- gluTessCallback(Tess, GLU_TESS_BEGIN, @DoTessBegin);
- gluTessCallback(tess, GLU_TESS_VERTEX, @DoTessVertex3fv);
- gluTessCallback(tess, GLU_TESS_END, @DoTessEnd);
- gluTessCallback(tess, GLU_TESS_ERROR, @DoTessError);
- gluTessCallback(tess, GLU_TESS_COMBINE, @DoTessCombine);
- if Assigned(normal) then
- gluTessNormal(tess, normal^.X, normal^.Y, normal^.Z)
- else
- gluTessNormal(tess, 0, 1, 0);
- // start tesselation of polygon
- gluTessBeginPolygon(tess, nil);
- // build outline, a polygon can have multiple outlines.
- gluTessBeginContour(tess);
- TessExtraVertices := 0;
- if invertNormals then
- begin
- for i := Vertexes.Count - 1 downto 0 do
- begin
- SetVector(dblVector, Vertexes.Items[i]);
- gluTessVertex(tess, dblVector, Vertexes.ItemAddress[i]);
- end;
- end
- else
- begin
- for i := 0 to Vertexes.Count - 1 do
- begin
- SetVector(dblVector, Vertexes.Items[i]);
- gluTessVertex(tess, dblVector, Vertexes.ItemAddress[i]);
- end;
- end;
- gluTessEndContour(tess);
- // End Tesselation of polygon, THIS is where the data is processed! (And all the events triggered!)
- gluTessEndPolygon(tess);
- // Delete the Tessellation GLU object.
- gluDeleteTess(tess);
- // deallocate extra buffer used by GLU in complex polygons.
- FreeMem(TessVertices, TessVerticesCount * SizeOf(TAffineVector));
- end;
- end.
|