fOdeClothify.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. unit fOdeClothify;
  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. GLS.VectorTypes,
  24. GLS.VectorLists,
  25. GLS.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. GLS.Utils,
  36. GLS.Material,
  37. GLS.Coordinates,
  38. GLS.RenderContextInfo,
  39. GLS.State,
  40. GLS.Context,
  41. GLS.BaseClasses,
  42. Imports.ODE,
  43. Physics.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. VCSphere: TGLVerletFricSphere;
  126. end;
  127. procedure RecalcMeshNormals(BaseMesh: TGLBaseMesh);
  128. procedure PrepareMeshForNormalsRecalc(BaseMesh: TGLBaseMesh);
  129. var
  130. FormClothify: TFormClothify;
  131. implementation
  132. {$R *.dfm}
  133. procedure TFormClothify.FormCreate(Sender: TObject);
  134. begin
  135. SetGLSceneMediaDir();
  136. ComboBox_MeshName.ItemIndex := 0;
  137. ComboBox_ConstraintType.ItemIndex := 0;
  138. ComboBox_Collider.ItemIndex := 3;
  139. ComboBox_ShadowChange(nil);
  140. Button_LoadMesh.Click;
  141. TrackBar_IterationsChange(nil);
  142. GLShadowVolume1.Occluders.AddCaster(GLActor1);
  143. end;
  144. procedure PrepareMeshForNormalsRecalc(BaseMesh: TGLBaseMesh);
  145. var
  146. i, j, k: Integer;
  147. mo: TMeshObject;
  148. fg: TFGVertexNormalTexIndexList;
  149. begin
  150. // update normals
  151. // (not very efficient, could use some work...)
  152. for i := 0 to BaseMesh.MeshObjects.Count - 1 do
  153. begin
  154. mo := BaseMesh.MeshObjects[i];
  155. for j := 0 to mo.FaceGroups.Count - 1 do
  156. begin
  157. if mo.FaceGroups[j] is TFGVertexNormalTexIndexList then
  158. begin
  159. fg := TFGVertexNormalTexIndexList(mo.FaceGroups[j]);
  160. for k := 0 to fg.VertexIndices.Count - 1 do
  161. begin
  162. fg.NormalIndices.List[k] := fg.VertexIndices.List[k];
  163. end;
  164. end;
  165. end;
  166. end;
  167. BaseMesh.StructureChanged;
  168. end;
  169. procedure RecalcMeshNormals(BaseMesh: TGLBaseMesh);
  170. var
  171. i, j, k: Integer;
  172. mo: TMeshObject;
  173. fg: TFGVertexIndexList;
  174. n: TAffineVector;
  175. begin
  176. // update normals
  177. // (not very efficient, could use some work...)
  178. for i := 0 to BaseMesh.MeshObjects.Count - 1 do
  179. begin
  180. mo := BaseMesh.MeshObjects[i];
  181. FillChar(mo.Normals.List[0], SizeOf(TAffineVector) * mo.Normals.Count, 0);
  182. for j := 0 to mo.FaceGroups.Count - 1 do
  183. begin
  184. if mo.FaceGroups[j] is TFGVertexIndexList then
  185. begin
  186. fg := TFGVertexIndexList(mo.FaceGroups[j]);
  187. k := 0;
  188. while k <= fg.VertexIndices.Count - 3 do
  189. begin
  190. n := CalcPlaneNormal(mo.Vertices.List[fg.VertexIndices.List[k]],
  191. mo.Vertices.List[fg.VertexIndices.List[k + 1]],
  192. mo.Vertices.List[fg.VertexIndices.List[k + 2]]);
  193. mo.Normals.TranslateItem(fg.VertexIndices.List[k], n);
  194. mo.Normals.TranslateItem(fg.VertexIndices.List[k + 1], n);
  195. mo.Normals.TranslateItem(fg.VertexIndices.List[k + 2], n); // }
  196. Inc(k, 3);
  197. end;
  198. end;
  199. end;
  200. mo.Normals.Normalize;
  201. end;
  202. BaseMesh.StructureChanged;
  203. end;
  204. procedure TFormClothify.Button_LoadMeshClick(Sender: TObject);
  205. var
  206. Floor: TGLVerletFloor;
  207. Capsule: TGLVerletFricCapsule;
  208. Cube: TGLVerletFricCube;
  209. Sides: TAffineVector;
  210. ColliderGravy: Single;
  211. s: string;
  212. f: single;
  213. p: Integer;
  214. procedure CreateCubeFromGLCube(GLCube: TGLCube);
  215. begin
  216. Cube := TGLVerletFricCube.Create(VerletWorld);
  217. Cube.Location := AffineVectorMake(GLCube.AbsolutePosition);
  218. Cube.FrictionRatio := 0.1;
  219. Sides.X := GLCube.CubeWidth * 1.1;
  220. Sides.Y := GLCube.CubeHeight * 1.1;
  221. Sides.Z := GLCube.CubeDepth * 1.1;
  222. Cube.Sides := Sides; // }
  223. end;
  224. procedure CreateODEWorld;
  225. var
  226. m: TdMass;
  227. begin
  228. GLSphere1.Visible := true;
  229. world := dWorldCreate;
  230. dWorldSetGravity(world, 0, -9.81, 0);
  231. contactgroup := dJointGroupCreate(0);
  232. space := dHashSpaceCreate(nil);
  233. body := dBodyCreate(world);
  234. dMassSetSphere(m, 0.1, GLSphere1.Radius);
  235. dCreatePlane(space, 0, 1, 0, GLShadowPlane1.Position.Y);
  236. ODESphere := dCreateSphere(space, GLSphere1.Radius);
  237. dGeomSetBody(ODESphere, body);
  238. dBodySetMass(body, @m);
  239. /// How to set centre of mass to origin ???
  240. ODESphere.data := GLSphere1;
  241. PositionSceneObjectForGeom(ODESphere);
  242. end;
  243. begin
  244. randomize;
  245. if world <> nil then
  246. begin
  247. dWorldDestroy(world);
  248. world := nil;
  249. GLSphere1.Position.AsAffineVector := NullVector;
  250. end;
  251. FreeAndNil(VerletWorld);
  252. FreeAndNil(EdgeDetector);
  253. s := ComboBox_MeshName.Items[MaxInteger(ComboBox_MeshName.ItemIndex, 0)];
  254. System.SysUtils.FormatSettings.DecimalSeparator := '.';
  255. p := Pos(',', s);
  256. if p > 0 then
  257. begin
  258. f := StrToFloatDef(Trim(Copy(s, p + 1, MaxInt)), 1);
  259. GLActor1.Scale.AsVector := VectorMake(f, f, f, 0)
  260. end
  261. else
  262. GLActor1.Scale.AsVector := XYZHmgVector;
  263. GLActor1.AutoCentering := [macUseBarycenter];
  264. GLActor1.LoadFromFile(Trim(Copy(s, 1, p - 1)));
  265. PrepareMeshForNormalsRecalc(GLActor1);
  266. GLActor1.Reference := aarNone;
  267. // This is what allows for FAST shadow volumes when using actors. Without
  268. // this line, it'll be _very_ slow.
  269. GLActor1.BuildSilhouetteConnectivityData;
  270. GLActor1.Roll(random * 360);
  271. GLActor1.Turn(random * 360); // }
  272. GLSphere1.Visible := false;
  273. GLCylinder1.Visible := false;
  274. GLCube1.Visible := false;
  275. GLDummyCube_Stairs.Visible := false;
  276. GL_Capsule.Visible := false;
  277. case ComboBox_Collider.ItemIndex of
  278. 0, -1:
  279. GLSphere1.Visible := true;
  280. 1:
  281. GLCylinder1.Visible := true;
  282. 2:
  283. GLCube1.Visible := true;
  284. 3:
  285. GLDummyCube_Stairs.Visible := true;
  286. 4:
  287. GL_Capsule.Visible := true;
  288. 5:
  289. CreateODEWorld;
  290. end;
  291. EdgeDetector := TGLEdgeDetector.Create(GLActor1);
  292. if not CheckBox_Weld.Checked then
  293. EdgeDetector.WeldDistance := -1;
  294. EdgeDetector.ProcessMesh;
  295. VerletWorld := TGLVerletWorld.Create;
  296. if CheckBox_UseOctree.Checked then
  297. VerletWorld.CreateOctree(AffineVectorMake(-20, -5.5, -20),
  298. AffineVectorMake(20, 20, 20), 25, 5); // }
  299. if CheckBox_SolidEdges.Checked then
  300. begin
  301. ColliderGravy := 1;
  302. EdgeDetector.AddEdgesAsSolidEdges(VerletWorld);
  303. end
  304. else
  305. ColliderGravy := 1.1;
  306. if ComboBox_ConstraintType.ItemIndex = 0 then
  307. EdgeDetector.AddEdgesAsSticks(VerletWorld, GetSlack)
  308. else
  309. EdgeDetector.AddEdgesAsSprings(VerletWorld, 1000, 100, GetSlack); // }
  310. // VerletWorld.Nodes[0].NailedDown := true;
  311. TGLVerletGravity.Create(VerletWorld);
  312. Floor := TGLVerletFloor.Create(VerletWorld);
  313. Floor.Location := VectorAdd(GLShadowPlane1.Position.AsAffineVector,
  314. AffineVectorMake(0, 0.1, 0));
  315. Floor.Normal := GLShadowPlane1.Direction.AsAffineVector;
  316. Floor.FrictionRatio := 0.6; // }
  317. if GLSphere1.Visible then
  318. begin
  319. VCSphere := TGLVerletFricSphere.Create(VerletWorld);
  320. VCSphere.Radius := GLSphere1.Radius * ColliderGravy;
  321. VCSphere.Location := AffineVectorMake(GLSphere1.AbsolutePosition);
  322. end;
  323. if GLCube1.Visible then
  324. begin
  325. CreateCubeFromGLCube(GLCube1);
  326. end;
  327. if GLCylinder1.Visible then
  328. begin
  329. Capsule := TGLVerletFricCapsule.Create(VerletWorld);
  330. Capsule.Radius := GLCylinder1.TopRadius * ColliderGravy;
  331. Capsule.Location := AffineVectorMake(GLCylinder1.AbsolutePosition);
  332. Capsule.Axis := AffineVectorMake(GLCylinder1.AbsoluteUp); // }
  333. Capsule.Length := 20;
  334. Capsule.FrictionRatio := 0.6;
  335. end;
  336. if GL_Capsule.Visible then
  337. begin
  338. Capsule := TGLVerletFricCapsule.Create(VerletWorld);
  339. Capsule.Radius := GL_Capsule.TopRadius * ColliderGravy;
  340. Capsule.Location := AffineVectorMake(GL_Capsule.AbsolutePosition);
  341. Capsule.Axis := AffineVectorMake(GL_Capsule.AbsoluteUp); // }
  342. Capsule.Length := GL_Capsule.Height * ColliderGravy;
  343. Capsule.FrictionRatio := 0.6;
  344. end;
  345. if GLDummyCube_Stairs.Visible then
  346. begin
  347. CreateCubeFromGLCube(GLCube_Stair1);
  348. CreateCubeFromGLCube(GLCube_Stair2);
  349. CreateCubeFromGLCube(GLCube_Stair3);
  350. CreateCubeFromGLCube(GLCube_Stair4);
  351. end;
  352. VerletWorld.SimTime := GLCadencer1.GetCurrentTime;
  353. VerletWorld.MaxDeltaTime := 0.01;
  354. VerletWorld.Iterations := TrackBar_Iterations.Position;
  355. TrackBar_FrictionChange(nil);
  356. GroupBox_LoadForm.Hide;
  357. CheckBox_ShowOctree.Enabled := CheckBox_UseOctree.Checked;
  358. TrackBar_Iterations.Enabled := (ComboBox_ConstraintType.ItemIndex = 0);
  359. TrackBar_Slack.Enabled := (ComboBox_ConstraintType.ItemIndex = 0);
  360. end;
  361. procedure TFormClothify.GLSceneViewer1MouseMove(Sender: TObject;
  362. Shift: TShiftState; X, Y: Integer);
  363. begin
  364. if ssLeft in Shift then
  365. GLCamera1.MoveAroundTarget(my - Y, mx - X);
  366. mx := X;
  367. my := Y
  368. end;
  369. procedure nearCallback(data: pointer; o1, o2: PdxGeom); cdecl;
  370. const
  371. cCOL_MAX = 3;
  372. var
  373. i: Integer;
  374. b1, b2: PdxBody;
  375. numc: Integer;
  376. contact: array [0 .. cCOL_MAX - 1] of TdContact;
  377. c: TdJointID;
  378. begin
  379. // exit without doing anything if the two bodies are connected by a joint
  380. b1 := dGeomGetBody(o1);
  381. b2 := dGeomGetBody(o2);
  382. if (assigned(b1) and assigned(b2) and (dAreConnected(b1, b2) <> 0)) then
  383. exit; // }
  384. for i := 0 to cCOL_MAX - 1 do
  385. begin
  386. contact[i].surface.mode := dContactBounce;
  387. // This determines friction, play around with it!
  388. contact[i].surface.mu := 10E9; // dInfinity; SHOULD BE INFINITY!
  389. contact[i].surface.mu2 := 0;
  390. contact[i].surface.bounce := 0.5; // 0.5;
  391. contact[i].surface.bounce_vel := 0.1;
  392. end;
  393. numc := dCollide(o1, o2, cCOL_MAX, contact[0].geom, SizeOf(TdContact));
  394. if (numc > 0) then
  395. begin
  396. // dMatrix3 RI;
  397. // dRSetIdentity (RI);
  398. // const dReal ss[3] = {0.02,0.02,0.02};
  399. for i := 0 to numc - 1 do
  400. begin
  401. c := dJointCreateContact(FormClothify.world, FormClothify.contactgroup,
  402. @contact[i]);
  403. dJointAttach(c, b1, b2);
  404. // dsDrawBox (contact[i].geom.pos,RI,ss);
  405. end;
  406. end;
  407. end;
  408. procedure TFormClothify.GLCadencer1Progress(Sender: TObject;
  409. const deltaTime, newTime: Double);
  410. begin
  411. { if CheckBox_Pause.Checked then
  412. VerletWorld.SimTime := newTime
  413. else// }
  414. begin
  415. if world <> nil then
  416. begin
  417. PositionSceneObjectForGeom(ODESphere);
  418. VCSphere.Location := GLSphere1.Position.AsAffineVector;
  419. dBodyAddForce(dGeomGetBody(ODESphere), VCSphere.KickbackForce.X,
  420. VCSphere.KickbackForce.Y, VCSphere.KickbackForce.Z);
  421. dSpaceCollide(space, nil, nearCallback);
  422. dWorldStep(world, VerletWorld.MaxDeltaTime);
  423. dJointGroupEmpty(contactgroup);
  424. end;
  425. VerletWorld.Progress(VerletWorld.MaxDeltaTime, newTime);
  426. RecalcMeshNormals(GLActor1);
  427. end;
  428. end;
  429. procedure TFormClothify.Timer1Timer(Sender: TObject);
  430. begin
  431. Label1.Caption := Format('%2.1f FPS', [GLSceneViewer1.FramesPerSecond]);
  432. GLSceneViewer1.ResetPerformanceMonitor;
  433. end;
  434. procedure TFormClothify.TrackBar_SlackChange(Sender: TObject);
  435. var
  436. i: Integer;
  437. begin
  438. for i := 0 to VerletWorld.Constraints.Count - 1 do
  439. begin
  440. if VerletWorld.Constraints[i] is TGLVerletStick then
  441. TGLVerletStick(VerletWorld.Constraints[i]).Slack := GetSlack;
  442. end;
  443. end;
  444. function TFormClothify.GetSlack: single;
  445. begin
  446. result := TrackBar_Slack.Position / 500;
  447. end;
  448. procedure TFormClothify.TrackBar_IterationsChange(Sender: TObject);
  449. begin
  450. VerletWorld.Iterations := TrackBar_Iterations.Position;
  451. Label6.Caption := Format('Iterations %d', [TrackBar_Iterations.Position]);
  452. end;
  453. procedure TFormClothify.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  454. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  455. begin
  456. GLCamera1.AdjustDistanceToTarget(Power(1.1, WheelDelta / 120));
  457. end;
  458. procedure TFormClothify.TrackBar_FrictionChange(Sender: TObject);
  459. var
  460. i: Integer;
  461. begin
  462. for i := 0 to VerletWorld.Constraints.Count - 1 do
  463. if VerletWorld.Constraints[i] is TGLVerletGlobalFrictionConstraint then
  464. TGLVerletGlobalFrictionConstraint(VerletWorld.Constraints[i])
  465. .FrictionRatio := TrackBar_Friction.Position / 100;
  466. end;
  467. procedure TFormClothify.GLDirectOpenGL1Render(Sender: TObject;
  468. var rci: TGLRenderContextInfo);
  469. procedure RenderAABB(AABB: TAABB; w, r, g, b: single);
  470. begin
  471. GL.Color3f(r, g, b);
  472. rci.GLStates.LineWidth := w;
  473. GL.Begin_(GL_LINE_STRIP);
  474. GL.Vertex3f(AABB.min.X, AABB.min.Y, AABB.min.Z);
  475. GL.Vertex3f(AABB.min.X, AABB.max.Y, AABB.min.Z);
  476. GL.Vertex3f(AABB.max.X, AABB.max.Y, AABB.min.Z);
  477. GL.Vertex3f(AABB.max.X, AABB.min.Y, AABB.min.Z);
  478. GL.Vertex3f(AABB.min.X, AABB.min.Y, AABB.min.Z);
  479. GL.Vertex3f(AABB.min.X, AABB.min.Y, AABB.max.Z);
  480. GL.Vertex3f(AABB.min.X, AABB.max.Y, AABB.max.Z);
  481. GL.Vertex3f(AABB.max.X, AABB.max.Y, AABB.max.Z);
  482. GL.Vertex3f(AABB.max.X, AABB.min.Y, AABB.max.Z);
  483. GL.Vertex3f(AABB.min.X, AABB.min.Y, AABB.max.Z);
  484. GL.End_;
  485. GL.Begin_(GL_LINES);
  486. GL.Vertex3f(AABB.min.X, AABB.max.Y, AABB.min.Z);
  487. GL.Vertex3f(AABB.min.X, AABB.max.Y, AABB.max.Z);
  488. GL.Vertex3f(AABB.max.X, AABB.max.Y, AABB.min.Z);
  489. GL.Vertex3f(AABB.max.X, AABB.max.Y, AABB.max.Z);
  490. GL.Vertex3f(AABB.max.X, AABB.min.Y, AABB.min.Z);
  491. GL.Vertex3f(AABB.max.X, AABB.min.Y, AABB.max.Z);
  492. GL.End_;
  493. end;
  494. procedure RenderOctreeNode(Node: TSectorNode);
  495. var
  496. i: Integer;
  497. AABB: TAABB;
  498. begin
  499. if Node.NoChildren then
  500. begin
  501. AABB := Node.AABB;
  502. if Node.RecursiveLeafCount > 0 then
  503. RenderAABB(AABB, 1, 0, 0, 0)
  504. else
  505. RenderAABB(AABB, 1, 0.8, 0.8, 0.8) // }
  506. end
  507. else
  508. begin
  509. for i := 0 to Node.ChildCount - 1 do
  510. RenderOctreeNode(Node.Children[i]);
  511. end;
  512. end;
  513. begin
  514. if CheckBox_ShowOctree.Checked and
  515. (VerletWorld.SpacePartition is TOctreeSpacePartition) then
  516. begin
  517. rci.GLStates.PushAttrib([sttEnable, sttCurrent, sttLine, sttColorBuffer]);
  518. rci.GLStates.Disable(stLighting);
  519. RenderOctreeNode(TOctreeSpacePartition(VerletWorld.SpacePartition)
  520. .RootNode);
  521. rci.GLStates.PopAttrib;
  522. end;
  523. end;
  524. procedure TFormClothify.Button_OpenLoadFormClick(Sender: TObject);
  525. begin
  526. GroupBox_LoadForm.Visible := true;
  527. GroupBox_LoadForm.SetFocus;
  528. end;
  529. procedure TFormClothify.Button_CancelLoadClick(Sender: TObject);
  530. begin
  531. GroupBox_LoadForm.Hide;
  532. end;
  533. procedure TFormClothify.ComboBox_ShadowChange(Sender: TObject);
  534. begin
  535. GLShadowVolume1.mode := svmOff;
  536. GLShadowPlane1.Visible := false;
  537. GLPlane1.Visible := true;
  538. GLSceneViewer1.Buffer.ContextOptions := GLSceneViewer1.Buffer.ContextOptions -
  539. [roStencilBuffer];
  540. case ComboBox_Shadow.ItemIndex of
  541. 0:
  542. ;
  543. 1:
  544. begin
  545. GLShadowVolume1.mode := svmDarkening;
  546. GLSceneViewer1.Buffer.ContextOptions :=
  547. GLSceneViewer1.Buffer.ContextOptions + [roStencilBuffer];
  548. end;
  549. 2:
  550. begin
  551. GLShadowPlane1.Visible := true;
  552. GLPlane1.Visible := false;
  553. GLSceneViewer1.Buffer.ContextOptions :=
  554. GLSceneViewer1.Buffer.ContextOptions + [roStencilBuffer];
  555. end;
  556. end;
  557. end;
  558. end.