GLFile3DSSceneObjects.pas 13 KB

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