2
// This unit is part of the GLScene Engine https://github.com/glscene
5
A scene object encapsulating the OpenGL feedback buffer.
7
This object, when Active, will render it's children using
8
the GL_FEEDBACK render mode. This will render the children
9
into the feedback Buffer rather than into the frame buffer.
11
Mesh data can be extracted from the buffer using the
12
BuildMeshFromBuffer procedure. For custom parsing of the
13
buffer use the Buffer SingleList. The Buffered property
14
will indicate if there is valid data in the buffer.
17
10/11/12 - PW - Added CPP compatibility: changed vector arrays to records
18
01/03/11 - Yar - Added Colors list to BuildMeshFromBuffer
19
23/08/10 - Yar - Added OpenGLTokens to uses, replaced OpenGL1x functions to OpenGLAdapter
20
15/06/10 - Yar - Bugfixed face culling on in feedback mode drawing (thanks Radli)
21
22/04/10 - Yar - Fixes after GLState revision
22
05/03/10 - DanB - More state added to TGLStateCache
23
30/03/07 - DaStr - Added $I GLScene.inc
24
28/03/07 - DaStr - Renamed parameters in some methods
25
(thanks Burkhard Carstens) (Bugtracker ID = 1678658)
26
23/07/04 - SG - Creation.
39
GLVectorGeometry, GLVectorLists, GLScene, GLVectorFileObjects,
40
GLTexture, GLRenderContextInfo, GLContext, GLState, OpenGLTokens,
45
TFeedbackMode = (fm2D, fm3D, fm3DColor, fm3DColorTexture, fm4DColorTexture);
48
{ An object encapsulating the OpenGL feedback rendering mode. }
49
TGLFeedback = class(TGLBaseSceneObject)
54
FMaxBufferSize: Cardinal;
56
FCorrectionScaling: Single;
61
procedure SetMaxBufferSize(const Value: Cardinal);
62
procedure SetMode(const Value: TFeedbackMode);
66
constructor Create(AOwner: TComponent); override;
67
destructor Destroy; override;
69
procedure DoRender(var ARci: TGLRenderContextInfo;
70
ARenderSelf, ARenderChildren: Boolean); override;
72
{ Parse the the feedback buffer for polygon data and build
73
a mesh into the assigned lists. }
74
procedure BuildMeshFromBuffer(
75
Vertices: TAffineVectorList = nil;
76
Normals: TAffineVectorList = nil;
77
Colors: TVectorList = nil;
78
TexCoords: TAffineVectorList = nil;
79
VertexIndices: TIntegerList = nil);
81
// True when there is data in the buffer ready for parsing
82
property Buffered: Boolean read FBuffered;
84
// The feedback buffer
85
property Buffer: TSingleList read FBuffer;
87
{ Vertex positions in the buffer needs to be scaled by
88
CorrectionScaling to get correct coordinates. }
89
property CorrectionScaling: Single read FCorrectionScaling;
94
// Maximum size allocated for the feedback buffer
95
property MaxBufferSize: Cardinal read FMaxBufferSize write SetMaxBufferSize;
96
// Toggles the feedback rendering
97
property Active: Boolean read FActive write FActive;
98
// The type of data that is collected in the feedback buffer
99
property Mode: TFeedbackMode read FMode write SetMode;
104
// ----------------------------------------------------------------------
105
// ----------------------------------------------------------------------
106
// ----------------------------------------------------------------------
108
// ----------------------------------------------------------------------
109
// ----------------------------------------------------------------------
110
// ----------------------------------------------------------------------
113
// ---------- TGLFeedback ----------
119
constructor TGLFeedback.Create(AOwner: TComponent);
123
FMaxBufferSize := $100000;
124
FBuffer := TSingleList.Create;
125
FBuffer.Capacity := FMaxBufferSize div SizeOf(Single);
128
FMode := fm3DColorTexture;
134
destructor TGLFeedback.Destroy;
144
procedure TGLFeedback.DoRender(var ARci: TGLRenderContextInfo;
145
ARenderSelf, ARenderChildren: Boolean);
147
function RecursChildRadius(obj: TGLBaseSceneObject): Single;
153
Result := obj.BoundingSphereRadius + VectorLength(obj.AbsolutePosition);
154
for i := 0 to obj.Count - 1 do
155
childRadius := RecursChildRadius(obj.Children[i]);
156
if childRadius > Result then
157
Result := childRadius;
167
if (csDesigning in ComponentState) or not Active then
169
if not ARenderChildren then
172
FCorrectionScaling := 1.0;
173
for i := 0 to Count - 1 do
175
radius := RecursChildRadius(Children[i]);
176
if radius > FCorrectionScaling then
177
FCorrectionScaling := radius + 1e-5;
181
fm2D: aType := GL_2D;
182
fm3D: aType := GL_3D;
183
fm3DColor: aType := GL_3D_COLOR;
184
fm3DColorTexture: aType := GL_3D_COLOR_TEXTURE;
185
fm4DColorTexture: aType := GL_4D_COLOR_TEXTURE;
187
aType := GL_3D_COLOR_TEXTURE;
190
FBuffer.Count := FMaxBufferSize div SizeOf(Single);
191
GL.FeedBackBuffer(FMaxBufferSize, atype, @FBuffer.List[0]);
192
ARci.GLStates.Disable(stCullFace);
193
ARci.ignoreMaterials := FMode < fm3DColor;
194
ARci.PipelineTransformation.Push;
195
ARci.PipelineTransformation.ProjectionMatrix := IdentityHmgMatrix;
196
ARci.PipelineTransformation.ViewMatrix :=
197
CreateScaleMatrix(VectorMake(
198
1.0 / FCorrectionScaling,
199
1.0 / FCorrectionScaling,
200
1.0 / FCorrectionScaling));
201
ARci.GLStates.ViewPort := Vector4iMake(-1, -1, 2, 2);
202
GL.RenderMode(GL_FEEDBACK);
204
Self.RenderChildren(0, Count - 1, ARci);
206
FBuffer.Count := GL.RenderMode(GL_RENDER);
207
ARci.PipelineTransformation.Pop;
210
ARci.ignoreMaterials := False;
211
FBuffered := (FBuffer.Count > 0);
212
if ARenderChildren then
213
Self.RenderChildren(0, Count - 1, ARci);
215
ARci.GLStates.ViewPort :=
216
Vector4iMake(0, 0, ARci.viewPortSize.cx, ARci.viewPortSize.cy);
219
// BuildMeshFromBuffer
222
procedure TGLFeedback.BuildMeshFromBuffer(
223
Vertices: TAffineVectorList = nil;
224
Normals: TAffineVectorList = nil;
225
Colors: TVectorList = nil;
226
TexCoords: TAffineVectorList = nil;
227
VertexIndices: TIntegerList = nil);
230
i, j, LCount, skip: Integer;
231
vertex, color, texcoord: TVector;
232
tempVertices, tempNormals, tempTexCoords: TAffineVectorList;
233
tempColors: TVectorList;
234
tempIndices: TIntegerList;
235
ColorBuffered, TexCoordBuffered: Boolean;
237
Assert(FMode <> fm2D, 'Cannot build mesh from fm2D feedback mode.');
239
tempVertices := TAffineVectorList.Create;
240
tempColors := TVectorList.Create;
241
tempTexCoords := TAffineVectorList.Create;
243
ColorBuffered := (FMode = fm3DColor) or
244
(FMode = fm3DColorTexture) or
245
(FMode = fm4DColorTexture);
246
TexCoordBuffered := (FMode = fm3DColorTexture) or
247
(FMode = fm4DColorTexture);
252
if FMode = fm4DColorTexture then
254
if ColorBuffered then
256
if TexCoordBuffered then
259
while i < FBuffer.Count - 1 do
262
if value = GL_POLYGON_TOKEN then
266
LCount := Round(value);
272
vertex.V[0] := FBuffer[i];
274
vertex.V[1] := FBuffer[i];
276
vertex.V[2] := FBuffer[i];
278
if FMode = fm4DColorTexture then
280
if ColorBuffered then
282
color.V[0] := FBuffer[i];
284
color.V[1] := FBuffer[i];
286
color.V[2] := FBuffer[i];
288
color.V[3] := FBuffer[i];
291
if TexCoordBuffered then
293
texcoord.V[0] := FBuffer[i];
295
texcoord.V[1] := FBuffer[i];
297
texcoord.V[2] := FBuffer[i];
299
texcoord.V[3] := FBuffer[i];
303
vertex.V[2] := 2 * vertex.V[2] - 1;
304
ScaleVector(vertex, FCorrectionScaling);
306
tempVertices.Add(AffineVectorMake(vertex));
307
tempColors.Add(color);
308
tempTexCoords.Add(AffineVectorMake(texcoord));
313
Inc(i, skip * LCount);
322
if Assigned(VertexIndices) then
324
tempIndices := BuildVectorCountOptimizedIndices(tempVertices, nil, nil);
325
RemapAndCleanupReferences(tempVertices, tempIndices);
326
VertexIndices.Assign(tempIndices);
330
tempIndices := TIntegerList.Create;
331
tempIndices.AddSerie(0, 1, tempVertices.Count);
334
tempNormals := BuildNormals(tempVertices, tempIndices);
336
if Assigned(Vertices) then
337
Vertices.Assign(tempVertices);
338
if Assigned(Normals) then
339
Normals.Assign(tempNormals);
340
if Assigned(Colors) and ColorBuffered then
341
Colors.Assign(tempColors);
342
if Assigned(TexCoords) and TexCoordBuffered then
343
TexCoords.Assign(tempTexCoords);
345
tempVertices.Destroy;
348
tempTexCoords.Destroy;
355
procedure TGLFeedback.SetMaxBufferSize(const Value: Cardinal);
357
if Value <> FMaxBufferSize then
359
FMaxBufferSize := Value;
362
FBuffer.Capacity := FMaxBufferSize div SizeOf(Single);
369
procedure TGLFeedback.SetMode(const Value: TFeedbackMode);
371
if Value <> FMode then
381
RegisterClasses([TGLFeedback]);