GXS.PolygonTesselation.pas 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. //
  2. // The graphics engine GLXEngine. The unit of GXScene for Delphi
  3. //
  4. unit GXS.PolygonTesselation;
  5. (* Code to generate triangle strips and fans for polygons *)
  6. interface
  7. {$I Stage.Defines.inc}
  8. uses
  9. Winapi.OpenGL,
  10. Winapi.OpenGLext,
  11. System.SysUtils,
  12. GXS.VectorFileObjects,
  13. GXS.VectorLists,
  14. Stage.VectorGeometry,
  15. Stage.VectorTypes;
  16. (* Tesselates the polygon outlined by the Vertexes.
  17. And addeds them to the first facegroup of the Mesh. *)
  18. procedure DoTesselate(Vertexes: TgxAffineVectorList;
  19. Mesh: TgxBaseMesh; normal: PAffineVector = nil; invertNormals: Boolean = False);
  20. implementation //-------------------------------------------------------------
  21. var
  22. TessMesh: TgxMeshObject;
  23. TessFace: TgxFGIndexTexCoordList;
  24. TessExtraVertices: Integer;
  25. TessVertices: PAffineVectorArray;
  26. procedure DoTessBegin(mode: GLEnum);
  27. {$IFDEF MSWIDOWS} stdcall;{$ELSE} cdecl;{$ENDIF}
  28. begin
  29. TessFace := TgxFGIndexTexCoordList.CreateOwned(TessMesh.FaceGroups);
  30. case mode of
  31. GL_TRIANGLES: TessFace.Mode := fgmmTriangles;
  32. GL_TRIANGLE_STRIP: TessFace.Mode := fgmmTriangleStrip;
  33. GL_TRIANGLE_FAN: TessFace.Mode := fgmmTriangleFan;
  34. end;
  35. end;
  36. procedure DoTessVertex3fv(v: PAffineVector);
  37. {$IFDEF MSWIDOWS} stdcall;{$ELSE} cdecl;{$ENDIF}
  38. begin
  39. TessFace.Add(TessMesh.Vertices.Add(v^), 0, 0);
  40. end;
  41. procedure DoTessEnd;
  42. {$IFDEF MSWIDOWS} stdcall;{$ELSE} cdecl;{$ENDIF}
  43. begin
  44. //
  45. end;
  46. procedure DoTessError(errno: GLEnum);
  47. {$IFDEF MSWIDOWS} stdcall;{$ELSE} cdecl;{$ENDIF}
  48. begin
  49. Assert(False, IntToStr(errno) + ': ' + string(gluErrorString(errno)));
  50. end;
  51. function AllocNewVertex: PAffineVector;
  52. begin
  53. Inc(TessExtraVertices);
  54. Result := @TessVertices[TessExtraVertices - 1];
  55. end;
  56. procedure DoTessCombine(coords: PDoubleVector; vertex_data: Pointer; weight: PGLFloat; var outData: Pointer);
  57. {$IFDEF MSWIDOWS} stdcall;{$ELSE} cdecl;{$ENDIF}
  58. begin
  59. outData := AllocNewVertex;
  60. SetVector(PAffineVector(outData)^, coords[0], coords[1], coords[2]);
  61. end;
  62. procedure DoTesselate(Vertexes: TgxAffineVectorList; Mesh: TgxBaseMesh; normal: PAffineVector = nil; invertNormals: Boolean = False);
  63. var
  64. Tess: GLUTesselator;
  65. i: Integer;
  66. dblVector: TAffineDblVector;
  67. begin
  68. // Select or Create FaceGroup
  69. if Mesh.MeshObjects.Count = 0 then
  70. begin
  71. TessMesh := TgxMeshObject.CreateOwned(Mesh.MeshObjects);
  72. Mesh.MeshObjects[0].Mode := momFaceGroups;
  73. end
  74. else
  75. TessMesh := Mesh.MeshObjects[0];
  76. // allocate extra buffer used by GLU in complex polygons.
  77. GetMem(TessVertices, Vertexes.Count * SizeOf(TAffineVector));
  78. // make a Tessellation GLU object.
  79. Tess := gluNewTess;
  80. // set up callback events
  81. gluTessCallback(Tess, GLU_TESS_BEGIN, @DoTessBegin);
  82. gluTessCallback(tess, GLU_TESS_VERTEX, @DoTessVertex3fv);
  83. gluTessCallback(tess, GLU_TESS_END, @DoTessEnd);
  84. gluTessCallback(tess, GLU_TESS_ERROR, @DoTessError);
  85. gluTessCallback(tess, GLU_TESS_COMBINE, @DoTessCombine);
  86. if Assigned(normal) then
  87. gluTessNormal(tess, normal^.X, normal^.Y, normal^.Z)
  88. else
  89. gluTessNormal(tess, 0, 1, 0);
  90. // start tesselation of polygon
  91. gluTessBeginPolygon(tess, nil);
  92. // build outline, a polygon can have multiple outlines.
  93. gluTessBeginContour(tess);
  94. TessExtraVertices := 0;
  95. if invertNormals then
  96. begin
  97. for i := Vertexes.Count - 1 downto 0 do
  98. begin
  99. SetVector(dblVector, Vertexes.Items[i]);
  100. gluTessVertex(tess, @dblVector, Vertexes.ItemAddress[i]);
  101. end;
  102. end
  103. else
  104. begin
  105. for i := 0 to Vertexes.Count - 1 do
  106. begin
  107. SetVector(dblVector, Vertexes.Items[i]);
  108. gluTessVertex(tess, @dblVector, Vertexes.ItemAddress[i]);
  109. end;
  110. end;
  111. gluTessEndContour(tess);
  112. // End Tesselation of polygon, THIS is where the data is processed! (And all the events triggered!)
  113. gluTessEndPolygon(tess);
  114. // Destroy the Tessellation GLU object.
  115. gluDeleteTess(tess);
  116. // deallocate extra buffer used by GLU in complex polygons.
  117. FreeMem(TessVertices, Vertexes.Count * SizeOf(TAffineVector));
  118. end;
  119. end.