LZScene

Форк
0
/
GLFile3DSSceneObjects.pas 
504 строки · 13.0 Кб
1
//
2
// This unit is part of the GLScene Engine https://github.com/glscene
3
//
4
{
5
  3ds-specific scene objects.
6

7
   History : 
8
       23/08/10 - Yar - Replaced OpenGL1x to OpenGLTokens
9
       22/04/10 - Yar - Fixes after GLState revision
10
       05/03/10 - DanB - More state added to TGLStateCache
11
       17/05/08 - DaStr - Added vGLFile3DSSceneObjects_RenderCameraAndLights
12
       06/04/08 - DaStr - Initial version (by Lexer)
13
   
14
}
15
unit GLFile3DSSceneObjects;
16

17
interface
18

19
{$I GLScene.inc}
20

21
uses
22
  // VCL
23
  Classes,
24
  SysUtils,
25
  Math,
26

27
  GLVectorGeometry, OpenGLTokens, OpenGLAdapter, GLContext, GLScene,
28
  GLVectorFileObjects, GLVectorTypes, GLPersistentClasses,
29
  GLCrossPlatform, GLCoordinates, GLRenderContextInfo, GLState;
30

31
type
32
  TGLFile3DSLight = class(TGLLightSource)
33
  private
34
    FTargetPos: TGLCoordinates;
35
    FHotSpot: Single;
36
    FMultipler: Single;
37
  public
38
    constructor Create(AOwner: TComponent); override;
39
    procedure DoRender(var rci: TGLRenderContextInfo; renderSelf, renderChildren: Boolean); override;
40
    procedure CoordinateChanged(Sender: TGLCustomCoordinates); override;
41
    destructor Destroy; override;
42
  published
43
    property SpotTargetPos: TGLCoordinates read FTargetPos;
44
    property HotSpot: Single read FHotSpot write FHotSpot;
45
    property Multipler: Single read FMultipler write FMultipler;
46
  end;
47

48
  TGLFile3DSCamera = class(TGLCamera)
49
  private
50
    FTargetPos: TGLCoordinates;
51
    FQuadCyl: array[0..1] of PGLUquadric;
52
    FQuadDisk: array[0..1] of PGLUquadric;
53
  public
54
    constructor Create(AOwner: TComponent); override;
55
    procedure DoRender(var rci: TGLRenderContextInfo; renderSelf, renderChildren: Boolean); override;
56
    procedure CoordinateChanged(Sender: TGLCustomCoordinates); override;
57
    destructor Destroy; override;
58
  published
59
    property CameraTargetPos: TGLCoordinates read FTargetPos;
60
    property RollAngle;
61
  end;
62

63
  TGLFile3DSActor = class(TGLActor)
64
  private
65
    procedure ReadMesh(Stream: TStream);
66
    procedure WriteMesh(Stream: TStream);
67
  protected
68
    procedure DefineProperties(Filer: TFiler); override;
69
  end;
70

71
  TGLFile3DSFreeForm = class(TGLFreeForm)
72
  private
73
    FTransfMat, FScaleMat, ParentMatrix: TMatrix;
74

75
    FS_Rot3DS: TGLCoordinates4;
76
    FRot3DS: TGLCoordinates4;
77
    FScale3DS: TGLCoordinates4;
78
    procedure ReadMesh(Stream: TStream);
79
    procedure WriteMesh(Stream: TStream);
80
  protected
81
    procedure DefineProperties(Filer: TFiler); override;
82
  public
83
    FRefMat: TMatrix;
84
    constructor Create(AOWner: TComponent); override;
85
    destructor Destroy; override;
86
    procedure BuildList(var rci: TGLRenderContextInfo); override;
87
    procedure CoordinateChanged(Sender: TGLCustomCoordinates); override;
88
    function AxisAlignedDimensionsUnscaled: TVector; override;
89
    function BarycenterAbsolutePosition: TVector; override;
90
  published
91
    property S_Rot3DS: TGLCoordinates4 read FS_Rot3DS;
92
    property Rot3DS: TGLCoordinates4 read FRot3DS;
93
    property Scale3DS: TGLCoordinates4 read FScale3DS;
94
  end;
95

96
var
97
  vGLFile3DSSceneObjects_RenderCameraAndLights: Boolean = False;
98

99
implementation
100

101
function MakeRotationQuaternion(const axis: TAffineVector; angle: Single): TQuaternion;
102
var
103
  v: Tvector;
104
  halfAngle, invAxisLengthMult: Single;
105
begin
106
  halfAngle := (angle) / 2;
107
  invAxisLengthMult := 1 / VectorLength(axis) * sin(halfAngle);
108

109
  v.V[0] := axis.V[0] * invAxisLengthMult;
110
  v.V[1] := axis.V[1] * invAxisLengthMult;
111
  v.V[2] := axis.V[2] * invAxisLengthMult;
112
  v.V[3] := cos(halfAngle);
113

114
  Result.ImagPart := AffineVectorMake(v);
115
  Result.RealPart := v.V[3];
116
end;
117

118
function QuaternionToRotateMatrix(const Quaternion: TQuaternion): TMatrix;
119
var
120
  wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2: Single;
121
  quat: TVector;
122
  m: TMatrix;
123
begin
124
  quat := VectorMake(Quaternion.ImagPart);
125
  quat.V[3] := Quaternion.RealPart;
126

127
  x2 := quat.V[0] + quat.V[0];
128
  y2 := quat.V[1] + quat.V[1];
129
  z2 := quat.V[2] + quat.V[2];
130
  xx := quat.V[0] * x2;
131
  xy := quat.V[0] * y2;
132
  xz := quat.V[0] * z2;
133
  yy := quat.V[1] * y2;
134
  yz := quat.V[1] * z2;
135
  zz := quat.V[2] * z2;
136
  wx := quat.V[3] * x2;
137
  wy := quat.V[3] * y2;
138
  wz := quat.V[3] * z2;
139

140
  m.V[0].V[0] := 1.0 - (yy + zz);
141
  m.V[0].V[1] := xy - wz;
142
  m.V[0].V[2] := xz + wy;
143
  m.V[1].V[0] := xy + wz;
144
  m.V[1].V[1] := 1.0 - (xx + zz);
145
  m.V[1].V[2] := yz - wx;
146
  m.V[2].V[0] := xz - wy;
147
  m.V[2].V[1] := yz + wx;
148
  m.V[2].V[2] := 1.0 - (xx + yy);
149

150
  m.V[0].V[3] := 0;
151
  m.V[1].V[3] := 0;
152
  m.V[2].V[3] := 0;
153
  m.V[3].V[0] := 0;
154
  m.V[3].V[1] := 0;
155
  m.V[3].V[2] := 0;
156
  m.V[3].V[3] := 1;
157

158
  Result := m;
159
end;
160

161
constructor TGLFile3DSLight.Create(AOwner: TComponent);
162
begin
163
  inherited;
164

165
  FTargetPos := TGLCoordinates.CreateInitialized(self, VectorMake(NullVector), csPoint);
166
  FHotSpot := 1;
167
  FMultipler := 1;
168
end;
169

170
procedure TGLFile3DSLight.DoRender(var rci: TGLRenderContextInfo; renderSelf, renderChildren: Boolean);
171

172
  procedure BuildFace;
173
  begin
174
    GL.Begin_(GL_TRIANGLES);
175
    GL.Vertex3f(0.03, 0, 0);
176
    GL.Vertex3f(0, 0.03, 0);
177
    GL.Vertex3f(0, 0, 0.07);
178
    GL.End_;
179
  end;
180

181
var
182
  dv: Single;
183

184
begin
185
  inherited;
186
  if not vGLFile3DSSceneObjects_RenderCameraAndLights then
187
    Exit;
188

189
  rci.GLStates.PolygonMode := pmLines;
190
  GL.PushMatrix;
191

192
  dv := VectorDistance(Position.AsVector, rci.cameraPosition);
193
  GL.Scalef(dv, dv, dv);
194

195
  // Up.
196
  BuildFace;
197
  GL.Rotatef(90, 0, 0, 1);
198
  BuildFace;
199
  GL.Rotatef(180, 0, 0, 1);
200
  BuildFace;
201
  GL.Rotatef(270, 0, 0, 1);
202
  BuildFace;
203

204
  // Down.
205
  GL.Rotatef(180, 0, 1, 0);
206
  BuildFace;
207
  GL.Rotatef(90, 0, 0, 1);
208
  BuildFace;
209
  GL.Rotatef(180, 0, 0, 1);
210
  BuildFace;
211
  GL.Rotatef(270, 0, 0, 1);
212
  BuildFace;
213

214
  GL.PopMatrix;
215
end;
216

217
procedure TGLFile3DSLight.CoordinateChanged(Sender: TGLCustomCoordinates);
218
begin
219
  inherited;
220

221
  if (Sender = FTargetPos) or (Sender = Position) then
222
    SpotDirection.SetVector(VectorNormalize(VectorSubtract(FTargetPos.AsAffineVector, Position.AsAffineVector)));
223
end;
224

225
destructor TGLFile3DSLight.Destroy;
226
begin
227
  FTargetPos.Free;
228
  inherited;
229
end;
230

231
constructor TGLFile3DSCamera.Create(AOwner: TComponent);
232
var
233
  I: Integer;
234
begin
235
  inherited;
236

237
  FTargetPos := TGLCoordinates.CreateInitialized(self, VectorMake(NullVector), csPoint);
238

239
  for I := 0 to 1 do
240
  begin
241
    //    FQuadCyl[I] := gluNewQuadric;
242
    //    FQuadDisk[I] := gluNewQuadric;
243
    //    gluQuadricNormals(FQuadCyl[I], GLU_SMOOTH);
244
    //    gluQuadricNormals(FQuadDisk[I], GLU_SMOOTH);
245
  end;
246
end;
247

248
procedure TGLFile3DSCamera.DoRender(var rci: TGLRenderContextInfo; renderSelf, renderChildren: Boolean);
249

250
  procedure BuildCyl;
251
  begin
252
    //    gluCylinder(FQuadCyl[0], 1, 1, 0.5, 6, 1);
253
    //    glTranslatef(0, 0, 0.5);
254
    //    gluDisk(FQuadDisk[0], 0, 1, 6, 1);
255
    GL.Translatef(0, 0, -0.5);
256
    rci.GLStates.InvertGLFrontFace;
257
    //    gluDisk(FQuadDisk[0], 0, 1, 6, 1);
258
    rci.GLStates.InvertGLFrontFace;
259
  end;
260

261
  procedure BuildFace;
262
  begin
263
    GL.Rotatef(-90, 0, 1, 0);
264
    GL.Rotatef(45, 0, 0, 1);
265
    GL.Translatef(0, -0.5, 1);
266
    //    gluCylinder(FQuadCyl[0], 0.5, 1.3, 2.4, 4, 1);
267
    GL.Translatef(0, 0, 2.4);
268
    //    gluDisk(FQuadDisk[0], 0, 1.3, 4, 1);
269
  end;
270

271
var
272
  dv, ang: Single;
273
  v, v1: TAffineVector;
274

275
begin
276
  inherited;
277
  if not vGLFile3DSSceneObjects_RenderCameraAndLights then
278
    Exit;
279

280
  v := VectorNormalize(VectorSubtract(FTargetPos.AsAffineVector, Position.AsAffineVector));
281

282
  v1 := AffineVectorMake(v.V[0], v.V[1], 0);
283
  NormalizeVector(v1);
284
  ang := GLVectorGeometry.arccos(VectorDotProduct(v, v1));
285

286
  rci.GLStates.PolygonMode := pmLines;
287

288
  GL.PushMatrix;
289
  GL.Rotatef(ang * 180 / pi, 0, 0, 1);
290
  dv := VectorDistance(Position.AsVector, rci.cameraPosition);
291
  GL.Scalef(dv / 25, dv / 25, dv / 25);
292

293
  GL.RotateF(90, 0, 1, 0);
294
  GL.Translatef(0, 1, 0);
295
  BuildCyl;
296
  GL.Translatef(1, -1, 0);
297
  BuildCyl;
298
  BuildFace;
299
  GL.PopMatrix;
300

301
  rci.GLStates.PolygonMode := pmFill;
302
end;
303

304
procedure TGLFile3DSCamera.CoordinateChanged(Sender: TGLCustomCoordinates);
305
begin
306
  inherited;
307

308
  if (Sender = FTargetPos) or (Sender = Position) then
309
  begin
310
    //    Up.AsAffineVector := ZVector;
311
    //    Direction.SetVector(VectorNormalize(VectorSubtract(FTargetPos.AsAffineVector, Position.AsAffineVector)));
312
  end;
313
end;
314

315
destructor TGLFile3DSCamera.Destroy;
316
var
317
  I: Integer;
318
begin
319
  inherited;
320
  FTargetPos.Free;
321
  for I := 0 to 1 do
322
  begin
323
    gluDeleteQuadric(FQuadCyl[I]);
324
    gluDeleteQuadric(FQuadDisk[I]);
325
  end;
326
end;
327

328
procedure TGLFile3DSActor.ReadMesh(Stream: TStream);
329
var
330
  virt: TBinaryReader;
331
begin
332
  virt := TBinaryReader.Create(Stream);
333
  MeshOBjects.ReadFromFiler(virt);
334
  virt.Free;
335
end;
336

337
procedure TGLFile3DSActor.WriteMesh(Stream: TStream);
338
var
339
  virt: TBinaryWriter;
340
begin
341
  virt := TBinaryWriter.Create(Stream);
342
  MeshOBjects.WriteToFiler(virt);
343
  virt.Free;
344
end;
345

346
procedure TGLFile3DSActor.DefineProperties(Filer: TFiler);
347
begin
348
  Filer.DefineBinaryProperty('MeshObjectsData', ReadMesh, WriteMesh, True);
349
end;
350

351
constructor TGLFile3DSFreeForm.Create(AOWner: TComponent);
352
begin
353
  inherited;
354

355
  FRefMat := IdentityHmgMatrix;
356
  FTransfMat := IdentityHmgMatrix;
357
  FScaleMat := IdentityHmgMatrix;
358
  FS_Rot3DS := TGLCoordinates4.CreateInitialized(self, VectorMake(1, 0, 0), csVector);
359
  FRot3DS := TGLCoordinates4.CreateInitialized(self, VectorMake(1, 0, 0), csVector);
360
  FScale3DS := TGLCoordinates4.CreateInitialized(self, VectorMake(1, 1, 1), csVector);
361

362
  ObjectStyle := [osDirectDraw];
363
end;
364

365
destructor TGLFile3DSFreeForm.Destroy;
366
begin
367
  FS_Rot3DS.Free;
368
  FRot3DS.Free;
369
  FScale3DS.Free;
370

371
  inherited;
372
end;
373

374
procedure TGLFile3DSFreeForm.ReadMesh(Stream: TStream);
375
var
376
  v: TVector;
377
  virt: TBinaryReader;
378
begin
379
  virt := TBinaryReader.Create(Stream);
380

381
  virt.read(FRefMat, sizeof(FRefMat));
382
  virt.read(v, sizeof(v));
383
  S_Rot3DS.SetVector(v);
384
  virt.read(v, sizeof(v));
385
  Rot3DS.SetVector(v);
386
  virt.read(v, sizeof(v));
387
  Scale3DS.SetVector(v);
388

389
  MeshOBjects.ReadFromFiler(virt);
390
  virt.Free;
391
end;
392

393
procedure TGLFile3DSFreeForm.WriteMesh(Stream: TStream);
394
var
395
  virt: TBinaryWriter;
396
  v: TVector;
397
begin
398
  virt := TBinaryWriter.Create(Stream);
399

400
  virt.write(FRefMat, sizeof(FRefMat));
401
  v := S_Rot3DS.AsVector;
402
  virt.write(v, sizeof(v));
403
  v := Rot3DS.AsVector;
404
  virt.write(v, sizeof(v));
405
  v := Scale3DS.AsVector;
406
  virt.write(v, sizeof(v));
407

408
  MeshOBjects.WriteToFiler(virt);
409
  virt.Free;
410
end;
411

412
procedure TGLFile3DSFreeForm.DefineProperties(Filer: TFiler);
413
begin
414
  Filer.DefineBinaryProperty('MeshObjectsData', ReadMesh, WriteMesh, True);
415
end;
416

417
procedure TGLFile3DSFreeForm.BuildList(var rci: TGLRenderContextInfo);
418
begin
419
  GL.MultMatrixf(@FTransfMat);
420
  GL.MultMatrixf(@FScaleMat);
421

422
  GL.PushMatrix;
423
  GL.MultMatrixf(@FRefMat);
424
  inherited;
425
  GL.PopMatrix;
426

427
  if parent is TGLFile3DSFreeForm then
428
    ParentMatrix := (parent as TGLFile3DSFreeForm).ParentMatrix
429
  else
430
    ParentMatrix := IdentityHmgMatrix;
431

432
  ParentMatrix := MatrixMultiply(FScaleMat, ParentMatrix);
433
  ParentMatrix := MatrixMultiply(FTransfMat, ParentMatrix);
434
end;
435

436
procedure TGLFile3DSFreeForm.CoordinateChanged(Sender: TGLCustomCoordinates);
437
var
438
  quat, quat1, quat2: TQuaternion;
439
begin
440
  inherited;
441

442
  if Sender.ClassType = FRot3DS.ClassType then
443
  begin
444
    quat1 := MakeRotationQuaternion(FS_Rot3DS.AsAffineVector, FS_Rot3DS.W);
445
    quat2 := MakeRotationQuaternion(FRot3DS.AsAffineVector, FRot3DS.W);
446

447
    quat := QuaternionMultiply(quat1, quat2);
448
    NormalizeQuaternion(quat);
449
    FTransfMat := QuaternionToRotateMatrix(quat);
450
    NormalizeMatrix(FTransfMat);
451
  end;
452
  if Sender.ClassType = FScale3DS.ClassType then
453
  begin
454
    FScaleMat := CreateScaleMatrix(FScale3DS.AsAffineVector);
455
  end;
456
end;
457

458
function TGLFile3DSFreeForm.AxisAlignedDimensionsUnscaled: TVector;
459
var
460
  dMin, dMax: TAffineVector;
461
  mat: TMatrix;
462
begin
463
  MeshObjects.GetExtents(dMin, dMax);
464
  mat := ParentMatrix;
465
  mat := MatrixMultiply(FRefMat, mat);
466
  if not IsInfinite(dMin.V[0]) then
467
    dMin := VectorTransform(dMin, mat);
468
  if not IsInfinite(dMax.V[0]) then
469
    dMax := VectorTransform(dMax, mat);
470

471
  Result.V[0] := (dMax.V[0] - dMin.V[0]) / 2;
472
  Result.V[1] := (dMax.V[1] - dMin.V[1]) / 2;
473
  Result.V[2] := (dMax.V[2] - dMin.V[2]) / 2;
474
  Result.V[3] := 0;
475
end;
476

477
// BarycenterAbsolutePosition
478
//
479

480
function TGLFile3DSFreeForm.BarycenterAbsolutePosition: TVector;
481
var
482
  dMin, dMax: TAffineVector;
483
  mat: TMatrix;
484
begin
485
  MeshObjects.GetExtents(dMin, dMax);
486
  mat := ParentMatrix;
487
  mat := MatrixMultiply(FRefMat, mat);
488
  if not IsInfinite(dMin.V[0]) then
489
    dMin := VectorTransform(dMin, mat);
490
  if not IsInfinite(dMax.V[0]) then
491
    dMax := VectorTransform(dMax, mat);
492

493
  Result.V[0] := (dMax.V[0] + dMin.V[0]) / 2;
494
  Result.V[1] := (dMax.V[1] + dMin.V[1]) / 2;
495
  Result.V[2] := (dMax.V[2] + dMin.V[2]) / 2;
496
  Result.V[3] := 1;
497

498
  Result := LocalToAbsolute(Result);
499
end;
500

501
initialization
502
  RegisterClasses([TGLFile3DSLight, TGLFile3DSCamera, TGLFile3DSActor, TGLFile3DSFreeForm]);
503

504
end.
505

506

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.