2
// This unit is part of the GLScene Engine https://github.com/glscene
5
3ds-specific scene objects.
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)
15
unit GLFile3DSSceneObjects;
27
GLVectorGeometry, OpenGLTokens, OpenGLAdapter, GLContext, GLScene,
28
GLVectorFileObjects, GLVectorTypes, GLPersistentClasses,
29
GLCrossPlatform, GLCoordinates, GLRenderContextInfo, GLState;
32
TGLFile3DSLight = class(TGLLightSource)
34
FTargetPos: TGLCoordinates;
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;
43
property SpotTargetPos: TGLCoordinates read FTargetPos;
44
property HotSpot: Single read FHotSpot write FHotSpot;
45
property Multipler: Single read FMultipler write FMultipler;
48
TGLFile3DSCamera = class(TGLCamera)
50
FTargetPos: TGLCoordinates;
51
FQuadCyl: array[0..1] of PGLUquadric;
52
FQuadDisk: array[0..1] of PGLUquadric;
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;
59
property CameraTargetPos: TGLCoordinates read FTargetPos;
63
TGLFile3DSActor = class(TGLActor)
65
procedure ReadMesh(Stream: TStream);
66
procedure WriteMesh(Stream: TStream);
68
procedure DefineProperties(Filer: TFiler); override;
71
TGLFile3DSFreeForm = class(TGLFreeForm)
73
FTransfMat, FScaleMat, ParentMatrix: TMatrix;
75
FS_Rot3DS: TGLCoordinates4;
76
FRot3DS: TGLCoordinates4;
77
FScale3DS: TGLCoordinates4;
78
procedure ReadMesh(Stream: TStream);
79
procedure WriteMesh(Stream: TStream);
81
procedure DefineProperties(Filer: TFiler); override;
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;
91
property S_Rot3DS: TGLCoordinates4 read FS_Rot3DS;
92
property Rot3DS: TGLCoordinates4 read FRot3DS;
93
property Scale3DS: TGLCoordinates4 read FScale3DS;
97
vGLFile3DSSceneObjects_RenderCameraAndLights: Boolean = False;
101
function MakeRotationQuaternion(const axis: TAffineVector; angle: Single): TQuaternion;
104
halfAngle, invAxisLengthMult: Single;
106
halfAngle := (angle) / 2;
107
invAxisLengthMult := 1 / VectorLength(axis) * sin(halfAngle);
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);
114
Result.ImagPart := AffineVectorMake(v);
115
Result.RealPart := v.V[3];
118
function QuaternionToRotateMatrix(const Quaternion: TQuaternion): TMatrix;
120
wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2: Single;
124
quat := VectorMake(Quaternion.ImagPart);
125
quat.V[3] := Quaternion.RealPart;
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;
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);
161
constructor TGLFile3DSLight.Create(AOwner: TComponent);
165
FTargetPos := TGLCoordinates.CreateInitialized(self, VectorMake(NullVector), csPoint);
170
procedure TGLFile3DSLight.DoRender(var rci: TGLRenderContextInfo; renderSelf, renderChildren: Boolean);
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);
186
if not vGLFile3DSSceneObjects_RenderCameraAndLights then
189
rci.GLStates.PolygonMode := pmLines;
192
dv := VectorDistance(Position.AsVector, rci.cameraPosition);
193
GL.Scalef(dv, dv, dv);
197
GL.Rotatef(90, 0, 0, 1);
199
GL.Rotatef(180, 0, 0, 1);
201
GL.Rotatef(270, 0, 0, 1);
205
GL.Rotatef(180, 0, 1, 0);
207
GL.Rotatef(90, 0, 0, 1);
209
GL.Rotatef(180, 0, 0, 1);
211
GL.Rotatef(270, 0, 0, 1);
217
procedure TGLFile3DSLight.CoordinateChanged(Sender: TGLCustomCoordinates);
221
if (Sender = FTargetPos) or (Sender = Position) then
222
SpotDirection.SetVector(VectorNormalize(VectorSubtract(FTargetPos.AsAffineVector, Position.AsAffineVector)));
225
destructor TGLFile3DSLight.Destroy;
231
constructor TGLFile3DSCamera.Create(AOwner: TComponent);
237
FTargetPos := TGLCoordinates.CreateInitialized(self, VectorMake(NullVector), csPoint);
241
// FQuadCyl[I] := gluNewQuadric;
242
// FQuadDisk[I] := gluNewQuadric;
243
// gluQuadricNormals(FQuadCyl[I], GLU_SMOOTH);
244
// gluQuadricNormals(FQuadDisk[I], GLU_SMOOTH);
248
procedure TGLFile3DSCamera.DoRender(var rci: TGLRenderContextInfo; renderSelf, renderChildren: Boolean);
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;
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);
273
v, v1: TAffineVector;
277
if not vGLFile3DSSceneObjects_RenderCameraAndLights then
280
v := VectorNormalize(VectorSubtract(FTargetPos.AsAffineVector, Position.AsAffineVector));
282
v1 := AffineVectorMake(v.V[0], v.V[1], 0);
284
ang := GLVectorGeometry.arccos(VectorDotProduct(v, v1));
286
rci.GLStates.PolygonMode := pmLines;
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);
293
GL.RotateF(90, 0, 1, 0);
294
GL.Translatef(0, 1, 0);
296
GL.Translatef(1, -1, 0);
301
rci.GLStates.PolygonMode := pmFill;
304
procedure TGLFile3DSCamera.CoordinateChanged(Sender: TGLCustomCoordinates);
308
if (Sender = FTargetPos) or (Sender = Position) then
310
// Up.AsAffineVector := ZVector;
311
// Direction.SetVector(VectorNormalize(VectorSubtract(FTargetPos.AsAffineVector, Position.AsAffineVector)));
315
destructor TGLFile3DSCamera.Destroy;
323
gluDeleteQuadric(FQuadCyl[I]);
324
gluDeleteQuadric(FQuadDisk[I]);
328
procedure TGLFile3DSActor.ReadMesh(Stream: TStream);
332
virt := TBinaryReader.Create(Stream);
333
MeshOBjects.ReadFromFiler(virt);
337
procedure TGLFile3DSActor.WriteMesh(Stream: TStream);
341
virt := TBinaryWriter.Create(Stream);
342
MeshOBjects.WriteToFiler(virt);
346
procedure TGLFile3DSActor.DefineProperties(Filer: TFiler);
348
Filer.DefineBinaryProperty('MeshObjectsData', ReadMesh, WriteMesh, True);
351
constructor TGLFile3DSFreeForm.Create(AOWner: TComponent);
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);
362
ObjectStyle := [osDirectDraw];
365
destructor TGLFile3DSFreeForm.Destroy;
374
procedure TGLFile3DSFreeForm.ReadMesh(Stream: TStream);
379
virt := TBinaryReader.Create(Stream);
381
virt.read(FRefMat, sizeof(FRefMat));
382
virt.read(v, sizeof(v));
383
S_Rot3DS.SetVector(v);
384
virt.read(v, sizeof(v));
386
virt.read(v, sizeof(v));
387
Scale3DS.SetVector(v);
389
MeshOBjects.ReadFromFiler(virt);
393
procedure TGLFile3DSFreeForm.WriteMesh(Stream: TStream);
398
virt := TBinaryWriter.Create(Stream);
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));
408
MeshOBjects.WriteToFiler(virt);
412
procedure TGLFile3DSFreeForm.DefineProperties(Filer: TFiler);
414
Filer.DefineBinaryProperty('MeshObjectsData', ReadMesh, WriteMesh, True);
417
procedure TGLFile3DSFreeForm.BuildList(var rci: TGLRenderContextInfo);
419
GL.MultMatrixf(@FTransfMat);
420
GL.MultMatrixf(@FScaleMat);
423
GL.MultMatrixf(@FRefMat);
427
if parent is TGLFile3DSFreeForm then
428
ParentMatrix := (parent as TGLFile3DSFreeForm).ParentMatrix
430
ParentMatrix := IdentityHmgMatrix;
432
ParentMatrix := MatrixMultiply(FScaleMat, ParentMatrix);
433
ParentMatrix := MatrixMultiply(FTransfMat, ParentMatrix);
436
procedure TGLFile3DSFreeForm.CoordinateChanged(Sender: TGLCustomCoordinates);
438
quat, quat1, quat2: TQuaternion;
442
if Sender.ClassType = FRot3DS.ClassType then
444
quat1 := MakeRotationQuaternion(FS_Rot3DS.AsAffineVector, FS_Rot3DS.W);
445
quat2 := MakeRotationQuaternion(FRot3DS.AsAffineVector, FRot3DS.W);
447
quat := QuaternionMultiply(quat1, quat2);
448
NormalizeQuaternion(quat);
449
FTransfMat := QuaternionToRotateMatrix(quat);
450
NormalizeMatrix(FTransfMat);
452
if Sender.ClassType = FScale3DS.ClassType then
454
FScaleMat := CreateScaleMatrix(FScale3DS.AsAffineVector);
458
function TGLFile3DSFreeForm.AxisAlignedDimensionsUnscaled: TVector;
460
dMin, dMax: TAffineVector;
463
MeshObjects.GetExtents(dMin, dMax);
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);
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;
477
// BarycenterAbsolutePosition
480
function TGLFile3DSFreeForm.BarycenterAbsolutePosition: TVector;
482
dMin, dMax: TAffineVector;
485
MeshObjects.GetExtents(dMin, dMax);
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);
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;
498
Result := LocalToAbsolute(Result);
502
RegisterClasses([TGLFile3DSLight, TGLFile3DSCamera, TGLFile3DSActor, TGLFile3DSFreeForm]);