GXS.File3DSSceneObjects.pas 12 KB

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