fDceDemo.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. unit fDceDemo;
  2. interface
  3. uses
  4. Winapi.Windows,
  5. Winapi.OpenGL,
  6. System.SysUtils,
  7. System.Classes,
  8. Vcl.Graphics,
  9. Vcl.Controls,
  10. Vcl.Forms,
  11. Vcl.Dialogs,
  12. Vcl.ExtCtrls,
  13. Vcl.Imaging.Jpeg,
  14. GLS.Scene,
  15. GLS.Objects,
  16. GLS.PersistentClasses,
  17. GLS.Cadencer,
  18. GLS.SceneViewer,
  19. GLS.DCE,
  20. GLS.Material,
  21. GLS.Texture,
  22. GLS.HeightData,
  23. GLS.TerrainRenderer,
  24. GLS.VectorFileObjects,
  25. GLS.BitmapFont,
  26. GLS.WindowsFont,
  27. GLS.HUDObjects,
  28. GLS.Coordinates,
  29. GLS.VectorGeometry,
  30. GLS.FileMD2,
  31. GLS.File3DS,
  32. GLS.Context,
  33. GLS.EllipseCollision,
  34. GLS.RenderContextInfo,
  35. GLS.Keyboard,
  36. GLS.ProxyObjects,
  37. GLS.State,
  38. GLS.Utils,
  39. GLS.BaseClasses,
  40. GLS.VectorTypes;
  41. type
  42. TFormDCE = class(TForm)
  43. GLScene1: TGLScene;
  44. GLSceneViewer1: TGLSceneViewer;
  45. GLCadencer1: TGLCadencer;
  46. GLCamera1: TGLCamera;
  47. Player: TGLDummyCube;
  48. GLDCEManager1: TGLDCEManager;
  49. Terrain: TGLTerrainRenderer;
  50. GLBitmapHDS1: TGLBitmapHDS;
  51. GLMatlLib: TGLMaterialLibrary;
  52. GLLightSource1: TGLLightSource;
  53. GLActor1: TGLActor;
  54. GLSphere1: TGLSphere;
  55. GLLightSource2: TGLLightSource;
  56. Balls: TGLDummyCube;
  57. GLWindowsBitmapFont1: TGLWindowsBitmapFont;
  58. Timer1: TTimer;
  59. GLHUDText1: TGLHUDText;
  60. Mushrooms: TGLDummyCube;
  61. moMushroom: TGLFreeForm;
  62. GLDirectOpenGL1: TGLDirectOpenGL;
  63. GLCube1: TGLCube;
  64. Help: TGLHUDText;
  65. HelpShadow: TGLHUDText;
  66. Ground: TGLPlane;
  67. procedure FormShow(Sender: TObject);
  68. procedure GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
  69. X, Y: Integer);
  70. procedure GLCadencer1Progress(Sender: TObject; const deltaTime,
  71. newTime: Double);
  72. procedure FormKeyDown(Sender: TObject; var Key: Word;
  73. Shift: TShiftState);
  74. procedure PlayerBehaviours0Collision(Sender: TObject;
  75. ObjectCollided: TGLBaseSceneObject; CollisionInfo: TDCECollision);
  76. procedure Timer1Timer(Sender: TObject);
  77. procedure GLDirectOpenGL1Render(Sender: TObject;
  78. var rci: TGLRenderContextInfo);
  79. public
  80. mx, my: Integer;
  81. Jumped: boolean;
  82. procedure Load;
  83. procedure HandleKeys;
  84. procedure HandleAnimation;
  85. procedure AddBall;
  86. procedure AddMushrooms;
  87. end;
  88. var
  89. FormDCE: TFormDCE;
  90. const
  91. cForce: Single = 250;
  92. cSpread = 200;
  93. cNbMushrooms = 20;
  94. implementation
  95. {$R *.dfm}
  96. { TForm1 }
  97. procedure TFormDCE.Load;
  98. begin
  99. SetGLSceneMediaDir();
  100. //Load Materials
  101. GLMatlLib.AddTextureMaterial('Terrain', 'snow512.jpg');
  102. GLMatlLib.AddTextureMaterial('Actor', 'waste.jpg');
  103. //Load Terrain
  104. GLBitmapHDS1.MaxPoolSize := 8 * 1024 * 1024;
  105. GLBitmapHDS1.Picture.LoadFromFile('terrain.bmp');
  106. Terrain.Direction.SetVector(0, 1, 0);
  107. Terrain.Material.LibMaterialName := 'Terrain';
  108. Terrain.TilesPerTexture := 256 / Terrain.TileSize;
  109. Terrain.Scale.SetVector(1, 1, 0.02);
  110. Ground.Material.LibMaterialName := 'Terrain';
  111. // Load mushroom mesh
  112. //Always use AutoScaling property or you may get some problems
  113. moMushRoom.AutoScaling.SetPoint(0.1, 0.1, 0.1);
  114. moMushRoom.LoadFromFile('Mushroom.3ds');
  115. moMushRoom.Direction.SetVector(0, 1, 0);
  116. moMushRoom.BuildOctree;
  117. //Load player
  118. Player.Position.SetPoint(0, 3, 0);
  119. //Actor
  120. GLActor1.LoadFromFile('Waste.md2');
  121. GLActor1.Direction.SetVector(0, 1, 0);
  122. GLActor1.Up.SetVector(1, 0, 0);
  123. GLActor1.Scale.SetVector(0.05, 0.05, 0.05);
  124. GLActor1.Material.LibMaterialName := 'Actor';
  125. GLActor1.Animations.LoadFromFile('Quake2Animations.aaf');
  126. // Define animation properties
  127. GLActor1.AnimationMode := aamLoop;
  128. GLActor1.SwitchToAnimation('stand');
  129. GLActor1.FrameInterpolation := afpLinear;
  130. //DCE Behaviour
  131. GLSphere1.Scale.Assign(GetOrCreateDCEDynamic(Player).Size);
  132. GetOrCreateDCEDynamic(Player).OnCollision := PlayerBehaviours0Collision;
  133. end;
  134. procedure TFormDCE.HandleKeys;
  135. var
  136. Force: TAffineVector;
  137. begin
  138. Force := NullVector;
  139. if IsKeyDown('w') or IsKeyDown('z') then
  140. Force.Z := cForce;
  141. if IsKeyDown('s') then
  142. Force.Z := -cForce;
  143. if IsKeyDown('a') or IsKeyDown('q') then
  144. Force.X := cForce;
  145. if IsKeyDown('d') then
  146. Force.X := -cForce;
  147. GetOrCreateDCEDynamic(Player).ApplyAccel(Force);
  148. end;
  149. procedure TFormDCE.HandleAnimation;
  150. var
  151. anim: string;
  152. begin
  153. if VectorNorm(GetOrCreateDCEDynamic(Player).Speed) > 0.1 then
  154. anim := 'run'
  155. else
  156. anim := 'stand';
  157. if Jumped then
  158. begin
  159. if (not GetOrCreateDCEDynamic(Player).InGround) then
  160. anim := 'jump'
  161. else
  162. Jumped := False;
  163. end;
  164. if anim = 'jump' then
  165. GLActor1.Interval := 500
  166. else
  167. GLActor1.Interval := 100;
  168. if GLActor1.CurrentAnimation <> anim then
  169. GLActor1.SwitchToAnimation(anim);
  170. end;
  171. procedure TFormDCE.AddBall;
  172. var
  173. Ball: TGLSphere;
  174. S: Single;
  175. begin
  176. Ball := TGLSphere(Balls.AddNewChild(TGLSphere));
  177. with Ball do
  178. begin
  179. Tag := 1; //set the identifier of a ball
  180. Radius := 1;
  181. S := (100 + Random(900)) / 500;
  182. Scale.SetVector(s, s, s);
  183. Position.SetPoint(
  184. Random(40) - Random(40),
  185. 4 + Random(10),
  186. Random(40) - Random(40));
  187. Material.FrontProperties.Diffuse.SetColor(
  188. (100 + Random(900)) / 1000,
  189. (100 + Random(900)) / 1000,
  190. (100 + Random(900)) / 1000);
  191. end;
  192. with GetOrCreateDCEDynamic(Ball) do
  193. begin
  194. Manager := GLDCEManager1;
  195. BounceFactor := 0.75;
  196. Friction := 0.1;
  197. SlideOrBounce := csbBounce;
  198. Size.Assign(Ball.Scale);
  199. end;
  200. end;
  201. procedure TFormDCE.AddMushrooms;
  202. var
  203. i: Integer;
  204. proxy: TGLFreeFormProxy;
  205. s: TGLVector;
  206. f: Single;
  207. begin
  208. // spawn some more mushrooms using proxy objects
  209. for i := 0 to cNbMushrooms - 1 do
  210. begin
  211. // create a new proxy and set its MasterObject property
  212. proxy := TGLFreeFormProxy(MushRooms.AddNewChild(TGLFreeFormProxy));
  213. with proxy do
  214. begin
  215. ProxyOptions := [pooObjects];
  216. MasterObject := moMushroom;
  217. // retrieve reference attitude
  218. Direction := moMushroom.Direction;
  219. Up := moMushroom.Up;
  220. // randomize scale
  221. s := moMushroom.Scale.AsVector;
  222. f := (2 * Random + 1);
  223. ScaleVector(s, f);
  224. Scale.AsVector := s;
  225. // randomize position
  226. Position.SetPoint(Random(cSpread) - (cSpread / 2),
  227. moMushroom.Position.z + 1.5 * f,
  228. Random(cSpread) - (cSpread / 2));
  229. // randomize orientation
  230. RollAngle := Random(360);
  231. TransformationChanged;
  232. end;
  233. with GetOrCreateDCEStatic(Proxy) do
  234. begin
  235. Manager := GLDCEManager1;
  236. BounceFactor := 0.75;
  237. Friction := 10;
  238. Shape := csFreeform;
  239. end;
  240. end;
  241. end;
  242. procedure TFormDCE.FormShow(Sender: TObject);
  243. begin
  244. Load;
  245. GLCadencer1.Enabled := true;
  246. Help.Text :=
  247. 'Mouse Drag - Look' + #13 +
  248. 'A,W,S,D - movement' + #13 +
  249. 'SPACE - Jump' + #13 +
  250. 'F1 - Add one ball' + #13 +
  251. 'F2 - Add 10 balls' + #13 +
  252. 'F3 - Add 20 mushrooms' + #13 +
  253. 'F4 - Change ground to box' + #13 +
  254. 'F5 - Toggle step mode' + #13 +
  255. 'RETURN - Reset';
  256. end;
  257. procedure TFormDCE.GLSceneViewer1MouseMove(Sender: TObject;
  258. Shift: TShiftState; X, Y: Integer);
  259. begin
  260. //Mouse look
  261. if ssLeft in Shift then
  262. begin
  263. GLCamera1.MoveAroundTarget((my - y), 0);
  264. Player.Turn(-(mx - x));
  265. end;
  266. mx := x;
  267. my := y;
  268. end;
  269. procedure TFormDCE.GLCadencer1Progress(Sender: TObject; const deltaTime,
  270. newTime: Double);
  271. begin
  272. HandleKeys;
  273. HandleAnimation;
  274. //This shows the manual progress, don't need this if you use the automatic mode
  275. if GLDCEManager1.ManualStep then
  276. GLDCEManager1.Step(deltaTime);
  277. Help.ModulateColor.Alpha := Help.ModulateColor.Alpha - (deltaTime * 0.05);
  278. if Help.ModulateColor.Alpha < 0.25 then
  279. Help.ModulateColor.Alpha := 0.25;
  280. HelpShadow.ModulateColor.Alpha := Help.ModulateColor.Alpha;
  281. HelpShadow.Text := Help.Text;
  282. end;
  283. procedure TFormDCE.FormKeyDown(Sender: TObject; var Key: Word;
  284. Shift: TShiftState);
  285. var
  286. i: integer;
  287. begin
  288. if Key = VK_F1 then
  289. AddBall;
  290. if Key = VK_F2 then
  291. for i := 1 to 10 do
  292. AddBall;
  293. if Key = VK_F3 then
  294. AddMushrooms;
  295. if (Key = VK_Space) then
  296. begin
  297. GetOrCreateDCEDynamic(Player).Jump(1, 20);
  298. Jumped := true;
  299. end;
  300. if key = VK_F4 then
  301. begin
  302. Terrain.Visible := False;
  303. Ground.Visible := true;
  304. GetOrCreateDCEStatic(Terrain).Active := False;
  305. GetOrCreateDCEStatic(Ground).Active := True;
  306. end;
  307. if key = VK_F5 then
  308. GLDCEManager1.ManualStep := not GLDCEManager1.ManualStep;
  309. if (Key = VK_RETURN) then
  310. begin
  311. Player.Position.SetPoint(0, 3, 0);
  312. Balls.DeleteChildren;
  313. MushRooms.DeleteChildren;
  314. Help.ModulateColor.Alpha := 1;
  315. Terrain.Visible := True;
  316. Ground.Visible := False;
  317. GetOrCreateDCEStatic(Terrain).Active := True;
  318. GetOrCreateDCEStatic(Ground).Active := False;
  319. end;
  320. end;
  321. procedure TFormDCE.PlayerBehaviours0Collision(Sender: TObject;
  322. ObjectCollided: TGLBaseSceneObject; CollisionInfo: TDCECollision);
  323. var
  324. v: TAffineVector;
  325. begin
  326. //Use some kind of identifier to know what object you are colliding
  327. //You can use the Tag, TagFloat, Name, Class
  328. if ObjectCollided.Tag = 1 then
  329. begin
  330. v := AffineVectorMake(VectorSubtract(ObjectCollided.AbsolutePosition, Player.AbsolutePosition));
  331. NormalizeVector(v);
  332. ScaleVector(v, 400);
  333. GetOrCreateDCEDynamic(ObjectCollided).StopAbsAccel;
  334. GetOrCreateDCEDynamic(ObjectCollided).ApplyAbsAccel(v);
  335. end;
  336. end;
  337. procedure TFormDCE.Timer1Timer(Sender: TObject);
  338. var
  339. s: string;
  340. begin
  341. if GLDCEManager1.ManualStep then
  342. s := 'Manual'
  343. else
  344. s := 'Automatic';
  345. GLHUDText1.Text := Format('FPS: %.1f - Dynamics: %d - Statics: %d - Step mode: %s',
  346. [GLSceneViewer1.FramesPerSecond, GLDCEManager1.DynamicCount, GLDCEManager1.StaticCount, s]);
  347. GLSceneViewer1.ResetPerformanceMonitor;
  348. end;
  349. procedure TFormDCE.GLDirectOpenGL1Render(Sender: TObject;
  350. var rci: TGLRenderContextInfo);
  351. var
  352. i: integer;
  353. p, n: TAffineVector;
  354. begin
  355. //To use this you will need to enable the debug define in the
  356. //GLEllipseCollision.pas, if you do, don't forget to clear the
  357. //triangle list! -> SetLength(debug_tri,0);
  358. rci.GLStates.PointSize := 5.0;
  359. glColor3f(0, 1, 0);
  360. for i := 0 to High(debug_tri) do
  361. with debug_tri[i] do
  362. begin
  363. glColor3f(0, 0, 0);
  364. glBegin(GL_LINE_STRIP);
  365. glVertex3f(p1.X, p1.Y, p1.Z);
  366. glVertex3f(p2.X, p2.Y, p2.Z);
  367. glVertex3f(p3.X, p3.Y, p3.Z);
  368. glEnd;
  369. CalcPlaneNormal(p1, p2, p3, n);
  370. ScaleVector(n, 0.25);
  371. p.X := (p1.X + p2.X + p3.X) / 3;
  372. p.Y := (p1.Y + p2.Y + p3.Y) / 3;
  373. p.Z := (p1.Z + p2.Z + p3.Z) / 3;
  374. glColor3f(0, 0, 1);
  375. glBegin(GL_LINE_STRIP);
  376. glVertex3f(p.X, p.Y, p.Z);
  377. glVertex3f(p.X + n.X, p.Y + n.Y, p.Z + n.Z);
  378. glEnd;
  379. glBegin(GL_POINTS);
  380. glVertex3f(p.X + n.X, p.Y + n.Y, p.Z + n.Z);
  381. glEnd;
  382. end; //}
  383. SetLength(debug_tri, 0);
  384. end;
  385. end.