fOdeClothifyD.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. unit fOdeClothifyD;
  2. interface
  3. uses
  4. Winapi.OpenGL,
  5. System.SysUtils,
  6. System.Classes,
  7. System.Types,
  8. System.Math,
  9. Vcl.Graphics,
  10. Vcl.Controls,
  11. Vcl.Forms,
  12. Vcl.ExtCtrls,
  13. Vcl.StdCtrls,
  14. Vcl.ComCtrls,
  15. GLS.Objects,
  16. GLS.Scene,
  17. GLS.PersistentClasses,
  18. GLS.VectorFileObjects,
  19. GLS.SceneViewer,
  20. GLS.FileMS3D,
  21. GLS.VerletTypes,
  22. GLS.VerletClothify,
  23. GLScene.VectorTypes,
  24. GLS.VectorLists,
  25. GLScene.VectorGeometry,
  26. GLS.Texture,
  27. GLS.FileSMD,
  28. GLS.Cadencer,
  29. GLS.ShadowPlane,
  30. GLS.File3DS,
  31. GLS.GeometryBB,
  32. GLS.SpacePartition,
  33. GLS.GeomObjects,
  34. GLS.ShadowVolume,
  35. GLScene.Utils,
  36. GLS.Material,
  37. GLS.Coordinates,
  38. GLS.RenderContextInfo,
  39. GLS.State,
  40. GLS.Context,
  41. GLS.BaseClasses,
  42. ODE.Import,
  43. GLS.ODEUtils;
  44. type
  45. TFormClothify = class(TForm)
  46. GLScene1: TGLScene;
  47. GLSceneViewer1: TGLSceneViewer;
  48. GLCamera1: TGLCamera;
  49. GLActor1: TGLActor;
  50. GLDummyCube1: TGLDummyCube;
  51. GLLightSource1: TGLLightSource;
  52. GLMaterialLibrary1: TGLMaterialLibrary;
  53. GLCadencer1: TGLCadencer;
  54. Timer1: TTimer;
  55. GLSphere1: TGLSphere;
  56. GLCylinder1: TGLCylinder;
  57. GLShadowPlane1: TGLShadowPlane;
  58. GLCube1: TGLCube;
  59. GLCube_Stair1: TGLCube;
  60. GLDummyCube_Stairs: TGLDummyCube;
  61. GLCube_Stair2: TGLCube;
  62. GLCube_Stair3: TGLCube;
  63. GLCube_Stair4: TGLCube;
  64. GLDummyCube2: TGLDummyCube;
  65. GL_Capsule: TGLCylinder;
  66. GLSphere2: TGLSphere;
  67. GLSphere3: TGLSphere;
  68. GLDummyCube_Light: TGLDummyCube;
  69. GLActor2: TGLActor;
  70. GLDirectOpenGL1: TGLDirectOpenGL;
  71. GroupBox_LoadForm: TGroupBox;
  72. Label2: TLabel;
  73. Label4: TLabel;
  74. Label5: TLabel;
  75. ComboBox_MeshName: TComboBox;
  76. ComboBox_ConstraintType: TComboBox;
  77. ComboBox_Collider: TComboBox;
  78. Button_LoadMesh: TButton;
  79. CheckBox_UseOctree: TCheckBox;
  80. CheckBox_SolidEdges: TCheckBox;
  81. CheckBox_Weld: TCheckBox;
  82. Button_CancelLoad: TButton;
  83. GLShadowVolume1: TGLShadowVolume;
  84. GLPlane1: TGLPlane;
  85. Panel1: TPanel;
  86. Label3: TLabel;
  87. TrackBar_Slack: TTrackBar;
  88. Label6: TLabel;
  89. TrackBar_Iterations: TTrackBar;
  90. Label7: TLabel;
  91. TrackBar_Friction: TTrackBar;
  92. CheckBox_ShowOctree: TCheckBox;
  93. Button_OpenLoadForm: TButton;
  94. Label8: TLabel;
  95. ComboBox_Shadow: TComboBox;
  96. Label1: TLabel;
  97. procedure GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
  98. X, Y: Integer);
  99. procedure GLCadencer1Progress(Sender: TObject;
  100. const deltaTime, newTime: Double);
  101. procedure Timer1Timer(Sender: TObject);
  102. procedure Button_LoadMeshClick(Sender: TObject);
  103. procedure FormCreate(Sender: TObject);
  104. procedure TrackBar_SlackChange(Sender: TObject);
  105. function GetSlack: single;
  106. procedure TrackBar_IterationsChange(Sender: TObject);
  107. procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
  108. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  109. procedure TrackBar_FrictionChange(Sender: TObject);
  110. procedure GLDirectOpenGL1Render(Sender: TObject;
  111. var rci: TGLRenderContextInfo);
  112. procedure Button_OpenLoadFormClick(Sender: TObject);
  113. procedure Button_CancelLoadClick(Sender: TObject);
  114. procedure ComboBox_ShadowChange(Sender: TObject);
  115. private
  116. public
  117. mx, my: Integer;
  118. VerletWorld: TGLVerletWorld;
  119. EdgeDetector: TGLEdgeDetector;
  120. world: PdxWorld;
  121. space: PdxSpace;
  122. ODESphere: PdxGeom;
  123. body: PdxBody;
  124. contactgroup: TdJointGroupID;
  125. VerletSphere: TGLVerletFrictionSphere;
  126. end;
  127. procedure RecalcMeshNormals(BaseMesh: TGLBaseMesh);
  128. procedure PrepareMeshForNormalsRecalc(BaseMesh: TGLBaseMesh);
  129. var
  130. FormClothify: TFormClothify;
  131. implementation
  132. {$R *.dfm}
  133. //-----------------------------------------------------------------
  134. procedure TFormClothify.FormCreate(Sender: TObject);
  135. begin
  136. var Path: TFileName := GetCurrentAssetPath();
  137. SetCurrentDir(Path + '\modelext');
  138. ComboBox_MeshName.ItemIndex := 0;
  139. ComboBox_ConstraintType.ItemIndex := 0;
  140. ComboBox_Collider.ItemIndex := 3;
  141. ComboBox_ShadowChange(nil);
  142. Button_LoadMesh.Click;
  143. TrackBar_IterationsChange(nil);
  144. GLShadowVolume1.Occluders.AddCaster(GLActor1);
  145. end;
  146. //-----------------------------------------------------------------
  147. procedure PrepareMeshForNormalsRecalc(BaseMesh: TGLBaseMesh);
  148. var
  149. i, j, k: Integer;
  150. mo: TGLMeshObject;
  151. fg: TFGVertexNormalTexIndexList;
  152. begin
  153. // update normals
  154. // (not very efficient, could use some work...)
  155. for i := 0 to BaseMesh.MeshObjects.Count - 1 do
  156. begin
  157. mo := BaseMesh.MeshObjects[i];
  158. for j := 0 to mo.FaceGroups.Count - 1 do
  159. begin
  160. if mo.FaceGroups[j] is TFGVertexNormalTexIndexList then
  161. begin
  162. fg := TFGVertexNormalTexIndexList(mo.FaceGroups[j]);
  163. for k := 0 to fg.VertexIndices.Count - 1 do
  164. begin
  165. fg.NormalIndices.List[k] := fg.VertexIndices.List[k];
  166. end;
  167. end;
  168. end;
  169. end;
  170. BaseMesh.StructureChanged;
  171. end;
  172. //-----------------------------------------------------------------
  173. procedure RecalcMeshNormals(BaseMesh: TGLBaseMesh);
  174. var
  175. i, j, k: Integer;
  176. mo: TGLMeshObject;
  177. fg: TFGVertexIndexList;
  178. n: TAffineVector;
  179. begin
  180. // update normals
  181. // (not very efficient, could use some work...)
  182. for i := 0 to BaseMesh.MeshObjects.Count - 1 do
  183. begin
  184. mo := BaseMesh.MeshObjects[i];
  185. FillChar(mo.Normals.List[0], SizeOf(TAffineVector) * mo.Normals.Count, 0);
  186. for j := 0 to mo.FaceGroups.Count - 1 do
  187. begin
  188. if mo.FaceGroups[j] is TFGVertexIndexList then
  189. begin
  190. fg := TFGVertexIndexList(mo.FaceGroups[j]);
  191. k := 0;
  192. while k <= fg.VertexIndices.Count - 3 do
  193. begin
  194. n := CalcPlaneNormal(mo.Vertices.List[fg.VertexIndices.List[k]],
  195. mo.Vertices.List[fg.VertexIndices.List[k + 1]],
  196. mo.Vertices.List[fg.VertexIndices.List[k + 2]]);
  197. mo.Normals.TranslateItem(fg.VertexIndices.List[k], n);
  198. mo.Normals.TranslateItem(fg.VertexIndices.List[k + 1], n);
  199. mo.Normals.TranslateItem(fg.VertexIndices.List[k + 2], n); // }
  200. Inc(k, 3);
  201. end;
  202. end;
  203. end;
  204. mo.Normals.Normalize;
  205. end;
  206. BaseMesh.StructureChanged;
  207. end;
  208. //----------------------------------------------------------------------
  209. procedure TFormClothify.Button_LoadMeshClick(Sender: TObject);
  210. var
  211. Floor: TGLVerletFloor;
  212. Capsule: TGLVerletFrictionCapsule;
  213. Cube: TGLVerletFrictionCube;
  214. Sides: TAffineVector;
  215. ColliderGravy: Single;
  216. s: string;
  217. f: single;
  218. p: Integer;
  219. procedure CreateCubeFromGLCube(GLCube: TGLCube);
  220. begin
  221. Cube := TGLVerletFrictionCube.Create(VerletWorld);
  222. Cube.Location := AffineVectorMake(GLCube.AbsolutePosition);
  223. Cube.FrictionRatio := 0.1;
  224. Sides.X := GLCube.CubeWidth * 1.1;
  225. Sides.Y := GLCube.CubeHeight * 1.1;
  226. Sides.Z := GLCube.CubeDepth * 1.1;
  227. Cube.Sides := Sides; // }
  228. end;
  229. procedure CreateODEWorld;
  230. var
  231. m: TdMass;
  232. begin
  233. GLSphere1.Visible := true;
  234. world := dWorldCreate;
  235. dWorldSetGravity(world, 0, -9.81, 0);
  236. contactgroup := dJointGroupCreate(0);
  237. space := dHashSpaceCreate(nil);
  238. body := dBodyCreate(world);
  239. dMassSetSphere(m, 0.1, GLSphere1.Radius);
  240. dCreatePlane(space, 0, 1, 0, GLShadowPlane1.Position.Y);
  241. ODESphere := dCreateSphere(space, GLSphere1.Radius);
  242. dGeomSetBody(ODESphere, body);
  243. dBodySetMass(body, @m);
  244. /// How to set centre of mass to origin ???
  245. ODESphere.data := GLSphere1;
  246. PositionSceneObjectForGeom(ODESphere);
  247. end;
  248. begin
  249. randomize;
  250. if world <> nil then
  251. begin
  252. dWorldDestroy(world);
  253. world := nil;
  254. GLSphere1.Position.AsAffineVector := NullVector;
  255. end;
  256. FreeAndNil(VerletWorld);
  257. FreeAndNil(EdgeDetector);
  258. s := ComboBox_MeshName.Items[MaxInteger(ComboBox_MeshName.ItemIndex, 0)];
  259. FormatSettings.DecimalSeparator := '.';
  260. p := Pos(',', s);
  261. if p > 0 then
  262. begin
  263. f := StrToFloatDef(Trim(Copy(s, p + 1, MaxInt)), 1);
  264. GLActor1.Scale.AsVector := VectorMake(f, f, f, 0)
  265. end
  266. else
  267. GLActor1.Scale.AsVector := XYZHmgVector;
  268. GLActor1.AutoCentering := [macUseBarycenter];
  269. GLActor1.LoadFromFile(Trim(Copy(s, 1, p - 1)));
  270. PrepareMeshForNormalsRecalc(GLActor1);
  271. GLActor1.Reference := aarNone;
  272. // This is what allows for FAST shadow volumes when using actors. Without
  273. // this line, it'll be _very_ slow.
  274. GLActor1.BuildSilhouetteConnectivityData;
  275. GLActor1.Roll(random * 360);
  276. GLActor1.Turn(random * 360); // }
  277. GLSphere1.Visible := false;
  278. GLCylinder1.Visible := false;
  279. GLCube1.Visible := false;
  280. GLDummyCube_Stairs.Visible := false;
  281. GL_Capsule.Visible := false;
  282. case ComboBox_Collider.ItemIndex of
  283. 0, -1:
  284. GLSphere1.Visible := true;
  285. 1:
  286. GLCylinder1.Visible := true;
  287. 2:
  288. GLCube1.Visible := true;
  289. 3:
  290. GLDummyCube_Stairs.Visible := true;
  291. 4:
  292. GL_Capsule.Visible := true;
  293. 5:
  294. CreateODEWorld;
  295. end;
  296. EdgeDetector := TGLEdgeDetector.Create(GLActor1);
  297. if not CheckBox_Weld.Checked then
  298. EdgeDetector.WeldDistance := -1;
  299. EdgeDetector.ProcessMesh;
  300. VerletWorld := TGLVerletWorld.Create;
  301. if CheckBox_UseOctree.Checked then
  302. VerletWorld.CreateOctree(AffineVectorMake(-20, -5.5, -20),
  303. AffineVectorMake(20, 20, 20), 25, 5); // }
  304. if CheckBox_SolidEdges.Checked then
  305. begin
  306. ColliderGravy := 1;
  307. EdgeDetector.AddEdgesAsSolidEdges(VerletWorld);
  308. end
  309. else
  310. ColliderGravy := 1.1;
  311. if ComboBox_ConstraintType.ItemIndex = 0 then
  312. EdgeDetector.AddEdgesAsSticks(VerletWorld, GetSlack)
  313. else
  314. EdgeDetector.AddEdgesAsSprings(VerletWorld, 1000, 100, GetSlack); // }
  315. // VerletWorld.Nodes[0].NailedDown := true;
  316. TGLVerletGravity.Create(VerletWorld);
  317. Floor := TGLVerletFloor.Create(VerletWorld);
  318. Floor.Location := VectorAdd(GLShadowPlane1.Position.AsAffineVector,
  319. AffineVectorMake(0, 0.1, 0));
  320. Floor.Normal := GLShadowPlane1.Direction.AsAffineVector;
  321. Floor.FrictionRatio := 0.6; // }
  322. if GLSphere1.Visible then
  323. begin
  324. VerletSphere := TGLVerletFrictionSphere.Create(VerletWorld);
  325. VerletSphere.Radius := GLSphere1.Radius * ColliderGravy;
  326. VerletSphere.Location := AffineVectorMake(GLSphere1.AbsolutePosition);
  327. end;
  328. if GLCube1.Visible then
  329. begin
  330. CreateCubeFromGLCube(GLCube1);
  331. end;
  332. if GLCylinder1.Visible then
  333. begin
  334. Capsule := TGLVerletFrictionCapsule.Create(VerletWorld);
  335. Capsule.Radius := GLCylinder1.TopRadius * ColliderGravy;
  336. Capsule.Location := AffineVectorMake(GLCylinder1.AbsolutePosition);
  337. Capsule.Axis := AffineVectorMake(GLCylinder1.AbsoluteUp); // }
  338. Capsule.Length := 20;
  339. Capsule.FrictionRatio := 0.6;
  340. end;
  341. if GL_Capsule.Visible then
  342. begin
  343. Capsule := TGLVerletFrictionCapsule.Create(VerletWorld);
  344. Capsule.Radius := GL_Capsule.TopRadius * ColliderGravy;
  345. Capsule.Location := AffineVectorMake(GL_Capsule.AbsolutePosition);
  346. Capsule.Axis := AffineVectorMake(GL_Capsule.AbsoluteUp); // }
  347. Capsule.Length := GL_Capsule.Height * ColliderGravy;
  348. Capsule.FrictionRatio := 0.6;
  349. end;
  350. if GLDummyCube_Stairs.Visible then
  351. begin
  352. CreateCubeFromGLCube(GLCube_Stair1);
  353. CreateCubeFromGLCube(GLCube_Stair2);
  354. CreateCubeFromGLCube(GLCube_Stair3);
  355. CreateCubeFromGLCube(GLCube_Stair4);
  356. end;
  357. VerletWorld.SimTime := GLCadencer1.GetCurrentTime;
  358. VerletWorld.MaxDeltaTime := 0.01;
  359. VerletWorld.Iterations := TrackBar_Iterations.Position;
  360. TrackBar_FrictionChange(nil);
  361. GroupBox_LoadForm.Hide;
  362. CheckBox_ShowOctree.Enabled := CheckBox_UseOctree.Checked;
  363. TrackBar_Iterations.Enabled := (ComboBox_ConstraintType.ItemIndex = 0);
  364. TrackBar_Slack.Enabled := (ComboBox_ConstraintType.ItemIndex = 0);
  365. end;
  366. procedure TFormClothify.GLSceneViewer1MouseMove(Sender: TObject;
  367. Shift: TShiftState; X, Y: Integer);
  368. begin
  369. if ssLeft in Shift then
  370. GLCamera1.MoveAroundTarget(my - Y, mx - X);
  371. mx := X;
  372. my := Y
  373. end;
  374. procedure nearCallback(data: pointer; o1, o2: PdxGeom); cdecl;
  375. const
  376. cCOL_MAX = 3;
  377. var
  378. i: Integer;
  379. b1, b2: PdxBody;
  380. numc: Integer;
  381. contact: array [0 .. cCOL_MAX - 1] of TdContact;
  382. c: TdJointID;
  383. begin
  384. // exit without doing anything if the two bodies are connected by a joint
  385. b1 := dGeomGetBody(o1);
  386. b2 := dGeomGetBody(o2);
  387. if (assigned(b1) and assigned(b2) and (dAreConnected(b1, b2) <> 0)) then
  388. exit; // }
  389. for i := 0 to cCOL_MAX - 1 do
  390. begin
  391. contact[i].surface.mode := dContactBounce;
  392. // This determines friction, play around with it!
  393. contact[i].surface.mu := 10E9; // dInfinity; SHOULD BE INFINITY!
  394. contact[i].surface.mu2 := 0;
  395. contact[i].surface.bounce := 0.5; // 0.5;
  396. contact[i].surface.bounce_vel := 0.1;
  397. end;
  398. numc := dCollide(o1, o2, cCOL_MAX, contact[0].geom, SizeOf(TdContact));
  399. if (numc > 0) then
  400. begin
  401. // dMatrix3 RI;
  402. // dRSetIdentity (RI);
  403. // const dReal ss[3] = {0.02,0.02,0.02};
  404. for i := 0 to numc - 1 do
  405. begin
  406. c := dJointCreateContact(FormClothify.world, FormClothify.contactgroup,
  407. @contact[i]);
  408. dJointAttach(c, b1, b2);
  409. // dsDrawBox (contact[i].geom.pos,RI,ss);
  410. end;
  411. end;
  412. end;
  413. //-------------------------------------------------------------
  414. procedure TFormClothify.GLCadencer1Progress(Sender: TObject;
  415. const deltaTime, newTime: Double);
  416. begin
  417. (* if CheckBox_Pause.Checked then
  418. VerletWorld.SimTime := newTime
  419. else// *)
  420. begin
  421. if world <> nil then
  422. begin
  423. PositionSceneObjectForGeom(ODESphere);
  424. VerletSphere.Location := GLSphere1.Position.AsAffineVector;
  425. dBodyAddForce(dGeomGetBody(ODESphere), VerletSphere.KickbackForce.X,
  426. VerletSphere.KickbackForce.Y, VerletSphere.KickbackForce.Z);
  427. dSpaceCollide(space, nil, nearCallback);
  428. dWorldStep(world, VerletWorld.MaxDeltaTime);
  429. dJointGroupEmpty(contactgroup);
  430. end;
  431. VerletWorld.Progress(VerletWorld.MaxDeltaTime, newTime);
  432. RecalcMeshNormals(GLActor1);
  433. end;
  434. end;
  435. //----------------------------------------------------------------
  436. procedure TFormClothify.Timer1Timer(Sender: TObject);
  437. begin
  438. Label1.Caption := Format('%2.1f FPS', [GLSceneViewer1.FramesPerSecond]);
  439. GLSceneViewer1.ResetPerformanceMonitor;
  440. end;
  441. procedure TFormClothify.TrackBar_SlackChange(Sender: TObject);
  442. var
  443. i: Integer;
  444. begin
  445. for i := 0 to VerletWorld.Constraints.Count - 1 do
  446. begin
  447. if VerletWorld.Constraints[i] is TGLVerletStick then
  448. TGLVerletStick(VerletWorld.Constraints[i]).Slack := GetSlack;
  449. end;
  450. end;
  451. function TFormClothify.GetSlack: single;
  452. begin
  453. result := TrackBar_Slack.Position / 500;
  454. end;
  455. procedure TFormClothify.TrackBar_IterationsChange(Sender: TObject);
  456. begin
  457. VerletWorld.Iterations := TrackBar_Iterations.Position;
  458. Label6.Caption := Format('Iterations %d', [TrackBar_Iterations.Position]);
  459. end;
  460. //-----------------------------------------------------------------------
  461. procedure TFormClothify.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  462. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  463. begin
  464. GLCamera1.AdjustDistanceToTarget(Power(1.1, WheelDelta / 120));
  465. end;
  466. procedure TFormClothify.TrackBar_FrictionChange(Sender: TObject);
  467. var
  468. i: Integer;
  469. begin
  470. for i := 0 to VerletWorld.Constraints.Count - 1 do
  471. if VerletWorld.Constraints[i] is TGLVerletGlobalFrictionConstraint then
  472. TGLVerletGlobalFrictionConstraint(VerletWorld.Constraints[i])
  473. .FrictionRatio := TrackBar_Friction.Position / 100;
  474. end;
  475. //------------------------------------------------------------------
  476. procedure TFormClothify.GLDirectOpenGL1Render(Sender: TObject;
  477. var rci: TGLRenderContextInfo);
  478. procedure RenderAABB(AABB: TAABB; w, r, g, b: single);
  479. begin
  480. glColor3f(r, g, b);
  481. rci.GLStates.LineWidth := w;
  482. glBegin(GL_LINE_STRIP);
  483. glVertex3f(AABB.min.X, AABB.min.Y, AABB.min.Z);
  484. glVertex3f(AABB.min.X, AABB.max.Y, AABB.min.Z);
  485. glVertex3f(AABB.max.X, AABB.max.Y, AABB.min.Z);
  486. glVertex3f(AABB.max.X, AABB.min.Y, AABB.min.Z);
  487. glVertex3f(AABB.min.X, AABB.min.Y, AABB.min.Z);
  488. glVertex3f(AABB.min.X, AABB.min.Y, AABB.max.Z);
  489. glVertex3f(AABB.min.X, AABB.max.Y, AABB.max.Z);
  490. glVertex3f(AABB.max.X, AABB.max.Y, AABB.max.Z);
  491. glVertex3f(AABB.max.X, AABB.min.Y, AABB.max.Z);
  492. glVertex3f(AABB.min.X, AABB.min.Y, AABB.max.Z);
  493. glEnd;
  494. glBegin(GL_LINES);
  495. glVertex3f(AABB.min.X, AABB.max.Y, AABB.min.Z);
  496. glVertex3f(AABB.min.X, AABB.max.Y, AABB.max.Z);
  497. glVertex3f(AABB.max.X, AABB.max.Y, AABB.min.Z);
  498. glVertex3f(AABB.max.X, AABB.max.Y, AABB.max.Z);
  499. glVertex3f(AABB.max.X, AABB.min.Y, AABB.min.Z);
  500. glVertex3f(AABB.max.X, AABB.min.Y, AABB.max.Z);
  501. glEnd;
  502. end;
  503. procedure RenderOctreeNode(Node: TGLSectorNode);
  504. var
  505. i: Integer;
  506. AABB: TAABB;
  507. begin
  508. if Node.NoChildren then
  509. begin
  510. AABB := Node.AABB;
  511. if Node.RecursiveLeafCount > 0 then
  512. RenderAABB(AABB, 1, 0, 0, 0)
  513. else
  514. RenderAABB(AABB, 1, 0.8, 0.8, 0.8) // }
  515. end
  516. else
  517. begin
  518. for i := 0 to Node.ChildCount - 1 do
  519. RenderOctreeNode(Node.Children[i]);
  520. end;
  521. end;
  522. begin
  523. if CheckBox_ShowOctree.Checked and
  524. (VerletWorld.SpacePartition is TGLOctreeSpacePartition) then
  525. begin
  526. rci.GLStates.PushAttrib([sttEnable, sttCurrent, sttLine, sttColorBuffer]);
  527. rci.GLStates.Disable(stLighting);
  528. RenderOctreeNode(TGLOctreeSpacePartition(VerletWorld.SpacePartition)
  529. .RootNode);
  530. rci.GLStates.PopAttrib;
  531. end;
  532. end;
  533. //--------------------------------------------------------------------
  534. procedure TFormClothify.Button_OpenLoadFormClick(Sender: TObject);
  535. begin
  536. GroupBox_LoadForm.Visible := true;
  537. GroupBox_LoadForm.SetFocus;
  538. end;
  539. procedure TFormClothify.Button_CancelLoadClick(Sender: TObject);
  540. begin
  541. GroupBox_LoadForm.Hide;
  542. end;
  543. //-------------------------------------------------------------------
  544. procedure TFormClothify.ComboBox_ShadowChange(Sender: TObject);
  545. begin
  546. GLShadowVolume1.mode := svmOff;
  547. GLShadowPlane1.Visible := false;
  548. GLPlane1.Visible := true;
  549. GLSceneViewer1.Buffer.ContextOptions := GLSceneViewer1.Buffer.ContextOptions -
  550. [roStencilBuffer];
  551. case ComboBox_Shadow.ItemIndex of
  552. 0:
  553. ;
  554. 1:
  555. begin
  556. GLShadowVolume1.mode := svmDarkening;
  557. GLSceneViewer1.Buffer.ContextOptions :=
  558. GLSceneViewer1.Buffer.ContextOptions + [roStencilBuffer];
  559. end;
  560. 2:
  561. begin
  562. GLShadowPlane1.Visible := true;
  563. GLPlane1.Visible := false;
  564. GLSceneViewer1.Buffer.ContextOptions :=
  565. GLSceneViewer1.Buffer.ContextOptions + [roStencilBuffer];
  566. end;
  567. end;
  568. end;
  569. end.