GLGLUTesselation.pas 4.2 KB

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