GXS.File3DSSceneObjects.pas 12 KB

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