GLS.File3DSSceneObjects.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. //
  2. // The multimedia graphics platform GLScene https://github.com/glscene
  3. //
  4. unit GLS.File3DSSceneObjects;
  5. (* 3ds-specific scene objects. *)
  6. interface
  7. {$I GLScene.inc}
  8. uses
  9. Winapi.OpenGL,
  10. System.Classes,
  11. System.SysUtils,
  12. System.Math,
  13. GLS.OpenGLTokens,
  14. GLS.OpenGLAdapter,
  15. GLS.VectorGeometry,
  16. GLS.Context,
  17. GLS.Scene,
  18. GLS.VectorFileObjects,
  19. GLS.VectorTypes,
  20. GLS.PersistentClasses,
  21. GLS.Coordinates,
  22. GLS.RenderContextInfo,
  23. GLS.State;
  24. type
  25. TGLFile3DSLight = class(TGLLightSource)
  26. private
  27. FTargetPos: TGLCoordinates;
  28. FHotSpot: Single;
  29. FMultipler: Single;
  30. public
  31. constructor Create(AOwner: TComponent); override;
  32. procedure DoRender(var rci: TGLRenderContextInfo; renderSelf, renderChildren: Boolean); override;
  33. procedure CoordinateChanged(Sender: TGLCustomCoordinates); override;
  34. destructor Destroy; override;
  35. published
  36. property SpotTargetPos: TGLCoordinates read FTargetPos;
  37. property HotSpot: Single read FHotSpot write FHotSpot;
  38. property Multipler: Single read FMultipler write FMultipler;
  39. end;
  40. TGLFile3DSCamera = class(TGLCamera)
  41. private
  42. FTargetPos: TGLCoordinates;
  43. FQuadCyl: array[0..1] of PGLUquadric;
  44. FQuadDisk: array[0..1] of PGLUquadric;
  45. public
  46. constructor Create(AOwner: TComponent); override;
  47. procedure DoRender(var rci: TGLRenderContextInfo; renderSelf, renderChildren: Boolean); override;
  48. procedure CoordinateChanged(Sender: TGLCustomCoordinates); override;
  49. destructor Destroy; override;
  50. published
  51. property CameraTargetPos: TGLCoordinates read FTargetPos;
  52. property RollAngle;
  53. end;
  54. TGLFile3DSActor = class(TGLActor)
  55. private
  56. procedure ReadMesh(Stream: TStream);
  57. procedure WriteMesh(Stream: TStream);
  58. protected
  59. procedure DefineProperties(Filer: TFiler); override;
  60. end;
  61. TGLFile3DSFreeForm = class(TGLFreeForm)
  62. private
  63. FTransfMat, FScaleMat, ParentMatrix: TGLMatrix;
  64. FS_Rot3DS: TGLCoordinates4;
  65. FRot3DS: TGLCoordinates4;
  66. FScale3DS: TGLCoordinates4;
  67. procedure ReadMesh(Stream: TStream);
  68. procedure WriteMesh(Stream: TStream);
  69. protected
  70. procedure DefineProperties(Filer: TFiler); override;
  71. public
  72. FRefMat: TGLMatrix;
  73. constructor Create(AOWner: TComponent); override;
  74. destructor Destroy; override;
  75. procedure BuildList(var rci: TGLRenderContextInfo); override;
  76. procedure CoordinateChanged(Sender: TGLCustomCoordinates); override;
  77. function AxisAlignedDimensionsUnscaled: TGLVector; override;
  78. function BarycenterAbsolutePosition: TGLVector; override;
  79. published
  80. property S_Rot3DS: TGLCoordinates4 read FS_Rot3DS;
  81. property Rot3DS: TGLCoordinates4 read FRot3DS;
  82. property Scale3DS: TGLCoordinates4 read FScale3DS;
  83. end;
  84. var
  85. vGLFile3DSSceneObjects_RenderCameraAndLights: Boolean = False;
  86. //---------------------------------------------------------
  87. implementation
  88. //---------------------------------------------------------
  89. function MakeRotationQuaternion(const axis: TAffineVector; angle: Single): TQuaternion;
  90. var
  91. v: TGLVector;
  92. halfAngle, invAxisLengthMult: Single;
  93. begin
  94. halfAngle := (angle) / 2;
  95. invAxisLengthMult := 1 / VectorLength(axis) * sin(halfAngle);
  96. v.X := axis.X * invAxisLengthMult;
  97. v.Y := axis.Y * invAxisLengthMult;
  98. v.Z := axis.Z * invAxisLengthMult;
  99. v.W := cos(halfAngle);
  100. Result.ImagPart := AffineVectorMake(v);
  101. Result.RealPart := v.W;
  102. end;
  103. function QuaternionToRotateMatrix(const Quaternion: TQuaternion): TGLMatrix;
  104. var
  105. wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2: Single;
  106. quat: TGLVector;
  107. m: TGLMatrix;
  108. begin
  109. quat := VectorMake(Quaternion.ImagPart);
  110. quat.W := Quaternion.RealPart;
  111. x2 := quat.X + quat.X;
  112. y2 := quat.Y + quat.Y;
  113. z2 := quat.Z + quat.Z;
  114. xx := quat.X * x2;
  115. xy := quat.X * y2;
  116. xz := quat.X * z2;
  117. yy := quat.Y * y2;
  118. yz := quat.Y * z2;
  119. zz := quat.Z * z2;
  120. wx := quat.W * x2;
  121. wy := quat.W * y2;
  122. wz := quat.W * z2;
  123. m.X.X := 1.0 - (yy + zz);
  124. m.X.Y := xy - wz;
  125. m.X.Z := xz + wy;
  126. m.Y.X := xy + wz;
  127. m.Y.Y := 1.0 - (xx + zz);
  128. m.Y.Z := yz - wx;
  129. m.Z.X := xz - wy;
  130. m.Z.Y := yz + wx;
  131. m.Z.Z := 1.0 - (xx + yy);
  132. m.X.W := 0;
  133. m.Y.W := 0;
  134. m.Z.W := 0;
  135. m.W.X := 0;
  136. m.W.Y := 0;
  137. m.W.Z := 0;
  138. m.W.W := 1;
  139. Result := m;
  140. end;
  141. constructor TGLFile3DSLight.Create(AOwner: TComponent);
  142. begin
  143. inherited;
  144. FTargetPos := TGLCoordinates.CreateInitialized(self, VectorMake(NullVector), csPoint);
  145. FHotSpot := 1;
  146. FMultipler := 1;
  147. end;
  148. procedure TGLFile3DSLight.DoRender(var rci: TGLRenderContextInfo; renderSelf, renderChildren: Boolean);
  149. procedure BuildFace;
  150. begin
  151. gl.Begin_(GL_TRIANGLES);
  152. gl.Vertex3f(0.03, 0, 0);
  153. gl.Vertex3f(0, 0.03, 0);
  154. gl.Vertex3f(0, 0, 0.07);
  155. gl.End_;
  156. end;
  157. var
  158. dv: Single;
  159. begin
  160. inherited;
  161. if not vGLFile3DSSceneObjects_RenderCameraAndLights then
  162. Exit;
  163. rci.GLStates.PolygonMode := pmLines;
  164. gl.PushMatrix;
  165. dv := VectorDistance(Position.AsVector, rci.cameraPosition);
  166. gl.Scalef(dv, dv, dv);
  167. // Up.
  168. BuildFace;
  169. gl.Rotatef(90, 0, 0, 1);
  170. BuildFace;
  171. gl.Rotatef(180, 0, 0, 1);
  172. BuildFace;
  173. gl.Rotatef(270, 0, 0, 1);
  174. BuildFace;
  175. // Down.
  176. gl.Rotatef(180, 0, 1, 0);
  177. BuildFace;
  178. gl.Rotatef(90, 0, 0, 1);
  179. BuildFace;
  180. gl.Rotatef(180, 0, 0, 1);
  181. BuildFace;
  182. gl.Rotatef(270, 0, 0, 1);
  183. BuildFace;
  184. gl.PopMatrix;
  185. end;
  186. procedure TGLFile3DSLight.CoordinateChanged(Sender: TGLCustomCoordinates);
  187. begin
  188. inherited;
  189. if (Sender = FTargetPos) or (Sender = Position) then
  190. SpotDirection.SetVector(VectorNormalize(VectorSubtract(FTargetPos.AsAffineVector, Position.AsAffineVector)));
  191. end;
  192. destructor TGLFile3DSLight.Destroy;
  193. begin
  194. FTargetPos.Free;
  195. inherited;
  196. end;
  197. constructor TGLFile3DSCamera.Create(AOwner: TComponent);
  198. var
  199. I: Integer;
  200. begin
  201. inherited;
  202. FTargetPos := TGLCoordinates.CreateInitialized(self, VectorMake(NullVector), csPoint);
  203. for I := 0 to 1 do
  204. begin
  205. // FQuadCyl[I] := gluNewQuadric;
  206. // FQuadDisk[I] := gluNewQuadric;
  207. // gluQuadricNormals(FQuadCyl[I], GLU_SMOOTH);
  208. // gluQuadricNormals(FQuadDisk[I], GLU_SMOOTH);
  209. end;
  210. end;
  211. procedure TGLFile3DSCamera.DoRender(var rci: TGLRenderContextInfo; renderSelf, renderChildren: Boolean);
  212. procedure BuildCyl;
  213. begin
  214. // gluCylinder(FQuadCyl[0], 1, 1, 0.5, 6, 1);
  215. // glTranslatef(0, 0, 0.5);
  216. // gluDisk(FQuadDisk[0], 0, 1, 6, 1);
  217. gl.Translatef(0, 0, -0.5);
  218. rci.GLStates.InvertGLFrontFace;
  219. // gluDisk(FQuadDisk[0], 0, 1, 6, 1);
  220. rci.GLStates.InvertGLFrontFace;
  221. end;
  222. procedure BuildFace;
  223. begin
  224. gl.Rotatef(-90, 0, 1, 0);
  225. gl.Rotatef(45, 0, 0, 1);
  226. gl.Translatef(0, -0.5, 1);
  227. // gluCylinder(FQuadCyl[0], 0.5, 1.3, 2.4, 4, 1);
  228. gl.Translatef(0, 0, 2.4);
  229. // gluDisk(FQuadDisk[0], 0, 1.3, 4, 1);
  230. end;
  231. var
  232. dv, ang: Single;
  233. v, v1: TAffineVector;
  234. begin
  235. inherited;
  236. if not vGLFile3DSSceneObjects_RenderCameraAndLights then
  237. Exit;
  238. v := VectorNormalize(VectorSubtract(FTargetPos.AsAffineVector, Position.AsAffineVector));
  239. v1 := AffineVectorMake(v.X, v.Y, 0);
  240. NormalizeVector(v1);
  241. ang := ArcCos(VectorDotProduct(v, v1));
  242. rci.GLStates.PolygonMode := pmLines;
  243. gl.PushMatrix;
  244. gl.Rotatef(ang * 180 / pi, 0, 0, 1);
  245. dv := VectorDistance(Position.AsVector, rci.cameraPosition);
  246. gl.Scalef(dv / 25, dv / 25, dv / 25);
  247. gl.RotateF(90, 0, 1, 0);
  248. gl.Translatef(0, 1, 0);
  249. BuildCyl;
  250. gl.Translatef(1, -1, 0);
  251. BuildCyl;
  252. BuildFace;
  253. gl.PopMatrix;
  254. rci.GLStates.PolygonMode := pmFill;
  255. end;
  256. procedure TGLFile3DSCamera.CoordinateChanged(Sender: TGLCustomCoordinates);
  257. begin
  258. inherited;
  259. if (Sender = FTargetPos) or (Sender = Position) then
  260. begin
  261. // Up.AsAffineVector := ZVector;
  262. // Direction.SetVector(VectorNormalize(VectorSubtract(FTargetPos.AsAffineVector, Position.AsAffineVector)));
  263. end;
  264. end;
  265. destructor TGLFile3DSCamera.Destroy;
  266. var
  267. I: Integer;
  268. begin
  269. inherited;
  270. FTargetPos.Free;
  271. for I := 0 to 1 do
  272. begin
  273. gluDeleteQuadric(FQuadCyl[I]);
  274. gluDeleteQuadric(FQuadDisk[I]);
  275. end;
  276. end;
  277. procedure TGLFile3DSActor.ReadMesh(Stream: TStream);
  278. var
  279. virt: TGLBinaryReader;
  280. begin
  281. virt := TGLBinaryReader.Create(Stream);
  282. MeshOBjects.ReadFromFiler(virt);
  283. virt.Free;
  284. end;
  285. procedure TGLFile3DSActor.WriteMesh(Stream: TStream);
  286. var
  287. virt: TGLBinaryWriter;
  288. begin
  289. virt := TGLBinaryWriter.Create(Stream);
  290. MeshOBjects.WriteToFiler(virt);
  291. virt.Free;
  292. end;
  293. procedure TGLFile3DSActor.DefineProperties(Filer: TFiler);
  294. begin
  295. Filer.DefineBinaryProperty('MeshObjectsData', ReadMesh, WriteMesh, True);
  296. end;
  297. constructor TGLFile3DSFreeForm.Create(AOWner: TComponent);
  298. begin
  299. inherited;
  300. FRefMat := IdentityHmgMatrix;
  301. FTransfMat := IdentityHmgMatrix;
  302. FScaleMat := IdentityHmgMatrix;
  303. FS_Rot3DS := TGLCoordinates4.CreateInitialized(self, VectorMake(1, 0, 0), csVector);
  304. FRot3DS := TGLCoordinates4.CreateInitialized(self, VectorMake(1, 0, 0), csVector);
  305. FScale3DS := TGLCoordinates4.CreateInitialized(self, VectorMake(1, 1, 1), csVector);
  306. ObjectStyle := [osDirectDraw];
  307. end;
  308. destructor TGLFile3DSFreeForm.Destroy;
  309. begin
  310. FS_Rot3DS.Free;
  311. FRot3DS.Free;
  312. FScale3DS.Free;
  313. inherited;
  314. end;
  315. procedure TGLFile3DSFreeForm.ReadMesh(Stream: TStream);
  316. var
  317. v: TGLVector;
  318. virt: TGLBinaryReader;
  319. begin
  320. virt := TGLBinaryReader.Create(Stream);
  321. virt.read(FRefMat, sizeof(FRefMat));
  322. virt.read(v, sizeof(v));
  323. S_Rot3DS.SetVector(v);
  324. virt.read(v, sizeof(v));
  325. Rot3DS.SetVector(v);
  326. virt.read(v, sizeof(v));
  327. Scale3DS.SetVector(v);
  328. MeshOBjects.ReadFromFiler(virt);
  329. virt.Free;
  330. end;
  331. procedure TGLFile3DSFreeForm.WriteMesh(Stream: TStream);
  332. var
  333. virt: TGLBinaryWriter;
  334. v: TGLVector;
  335. begin
  336. virt := TGLBinaryWriter.Create(Stream);
  337. virt.write(FRefMat, sizeof(FRefMat));
  338. v := S_Rot3DS.AsVector;
  339. virt.write(v, sizeof(v));
  340. v := Rot3DS.AsVector;
  341. virt.write(v, sizeof(v));
  342. v := Scale3DS.AsVector;
  343. virt.write(v, sizeof(v));
  344. MeshOBjects.WriteToFiler(virt);
  345. virt.Free;
  346. end;
  347. procedure TGLFile3DSFreeForm.DefineProperties(Filer: TFiler);
  348. begin
  349. Filer.DefineBinaryProperty('MeshObjectsData', ReadMesh, WriteMesh, True);
  350. end;
  351. procedure TGLFile3DSFreeForm.BuildList(var rci: TGLRenderContextInfo);
  352. begin
  353. gl.MultMatrixf(@FTransfMat);
  354. gl.MultMatrixf(@FScaleMat);
  355. gl.PushMatrix;
  356. gl.MultMatrixf(@FRefMat);
  357. inherited;
  358. gl.PopMatrix;
  359. if parent is TGLFile3DSFreeForm then
  360. ParentMatrix := (parent as TGLFile3DSFreeForm).ParentMatrix
  361. else
  362. ParentMatrix := IdentityHmgMatrix;
  363. ParentMatrix := MatrixMultiply(FScaleMat, ParentMatrix);
  364. ParentMatrix := MatrixMultiply(FTransfMat, ParentMatrix);
  365. end;
  366. procedure TGLFile3DSFreeForm.CoordinateChanged(Sender: TGLCustomCoordinates);
  367. var
  368. quat, quat1, quat2: TQuaternion;
  369. begin
  370. inherited;
  371. if Sender.ClassType = FRot3DS.ClassType then
  372. begin
  373. quat1 := MakeRotationQuaternion(FS_Rot3DS.AsAffineVector, FS_Rot3DS.W);
  374. quat2 := MakeRotationQuaternion(FRot3DS.AsAffineVector, FRot3DS.W);
  375. quat := QuaternionMultiply(quat1, quat2);
  376. NormalizeQuaternion(quat);
  377. FTransfMat := QuaternionToRotateMatrix(quat);
  378. NormalizeMatrix(FTransfMat);
  379. end;
  380. if Sender.ClassType = FScale3DS.ClassType then
  381. begin
  382. FScaleMat := CreateScaleMatrix(FScale3DS.AsAffineVector);
  383. end;
  384. end;
  385. function TGLFile3DSFreeForm.AxisAlignedDimensionsUnscaled: TGLVector;
  386. var
  387. dMin, dMax: TAffineVector;
  388. mat: TGLMatrix;
  389. begin
  390. MeshObjects.GetExtents(dMin, dMax);
  391. mat := ParentMatrix;
  392. mat := MatrixMultiply(FRefMat, mat);
  393. if not IsInfinite(dMin.X) then
  394. dMin := VectorTransform(dMin, mat);
  395. if not IsInfinite(dMax.X) then
  396. dMax := VectorTransform(dMax, mat);
  397. Result.X := (dMax.X - dMin.X) / 2;
  398. Result.Y := (dMax.Y - dMin.Y) / 2;
  399. Result.Z := (dMax.Z - dMin.Z) / 2;
  400. Result.W := 0;
  401. end;
  402. function TGLFile3DSFreeForm.BarycenterAbsolutePosition: TGLVector;
  403. var
  404. dMin, dMax: TAffineVector;
  405. mat: TGLMatrix;
  406. begin
  407. MeshObjects.GetExtents(dMin, dMax);
  408. mat := ParentMatrix;
  409. mat := MatrixMultiply(FRefMat, mat);
  410. if not IsInfinite(dMin.X) then
  411. dMin := VectorTransform(dMin, mat);
  412. if not IsInfinite(dMax.X) then
  413. dMax := VectorTransform(dMax, mat);
  414. Result.X := (dMax.X + dMin.X) / 2;
  415. Result.Y := (dMax.Y + dMin.Y) / 2;
  416. Result.Z := (dMax.Z + dMin.Z) / 2;
  417. Result.W := 1;
  418. Result := LocalToAbsolute(Result);
  419. end;
  420. initialization
  421. RegisterClasses([TGLFile3DSLight, TGLFile3DSCamera, TGLFile3DSActor, TGLFile3DSFreeForm]);
  422. end.