2
0

GLFile3DSSceneObjects.pas 13 KB

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