fDceDemoD.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. unit fDceDemoD;
  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. GLScene.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. GLScene.Utils,
  39. GLS.BaseClasses,
  40. GLScene.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. GLMatLib: 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. HUDTextCoords: TGLHUDText;
  68. procedure FormShow(Sender: TObject);
  69. procedure GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
  70. X, Y: Integer);
  71. procedure GLCadencer1Progress(Sender: TObject;
  72. const deltaTime, newTime: Double);
  73. procedure FormKeyDown(Sender: TObject; var Key: Word; 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: Integer = 200;
  93. cNbMushrooms = 20;
  94. implementation
  95. {$R *.dfm}
  96. //-----------------------------------------------------------------
  97. procedure TFormDCE.Load;
  98. begin
  99. var Path: TFileName := GetCurrentAssetPath();
  100. // Load texture material for terrain
  101. SetCurrentDir(Path + '\texture');
  102. GLMatLib.AddTextureMaterial('Terrain', 'snow512.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 static mushroom mesh
  112. SetCurrentDir(Path + '\model');
  113. // Always use AutoScaling property or you may get some problems
  114. moMushroom.AutoScaling.SetPoint(0.1, 0.1, 0.1);
  115. moMushroom.LoadFromFile('Mushroom.3ds');
  116. moMushroom.Direction.SetVector(0, 1, 0);
  117. moMushroom.BuildOctree();
  118. // Load player
  119. Player.Position.SetPoint(0.0, 3.0, 0.0);
  120. // Load dyn modelexts with textures and animations
  121. SetCurrentDir(Path + '\modelext');
  122. GLMatLib.AddTextureMaterial('Actor', 'waste.jpg');
  123. GLActor1.LoadFromFile('Waste.md2');
  124. GLActor1.Direction.SetVector(0, 1, 0);
  125. GLActor1.Up.SetVector(1, 0, 0);
  126. GLActor1.Scale.SetVector(0.05, 0.05, 0.05);
  127. GLActor1.Material.LibMaterialName := 'Actor';
  128. GLActor1.Animations.LoadFromFile('Quake2Animations.aaf');
  129. // Define animation properties
  130. GLActor1.AnimationMode := aamLoop;
  131. GLActor1.SwitchToAnimation('stand');
  132. GLActor1.FrameInterpolation := afpLinear;
  133. // DCE Behaviour
  134. GLSphere1.Scale.Assign(GetOrCreateDCEDynamic(Player).Size);
  135. GetOrCreateDCEDynamic(Player).OnCollision := PlayerBehaviours0Collision;
  136. end;
  137. //-----------------------------------------------------------------
  138. procedure TFormDCE.FormShow(Sender: TObject);
  139. begin
  140. Load;
  141. GLCadencer1.Enabled := true;
  142. Help.Text := 'Mouse Drag - Look' + #13 + 'A,W,S,D - movement' + #13 +
  143. 'SPACE - Jump' + #13 + 'F1 - Add one ball' + #13 + 'F2 - Add 10 balls' + #13
  144. + 'F3 - Add 20 mushrooms' + #13 + 'F4 - Change ground to box' + #13 +
  145. 'F5 - Toggle step mode' + #13 + 'RETURN - Reset';
  146. end;
  147. //-----------------------------------------------------------------
  148. procedure TFormDCE.AddBall;
  149. var
  150. Ball: TGLSphere;
  151. S: Single;
  152. begin
  153. Ball := TGLSphere(Balls.AddNewChild(TGLSphere));
  154. Ball.Tag := 1; // set the identifier of a ball
  155. Ball.Radius := 1;
  156. S := (100 + Random(900)) / 500;
  157. Ball.Scale.SetVector(S, S, S);
  158. Ball.Position.SetPoint(Random(40) - Random(40), 4 + Random(10),
  159. Random(40) - Random(40));
  160. Ball.Material.FrontProperties.Diffuse.SetColor((100 + Random(900)) / 1000,
  161. (100 + Random(900)) / 1000, (100 + Random(900)) / 1000);
  162. GetOrCreateDCEDynamic(Ball).Manager := GLDCEManager1;
  163. GetOrCreateDCEDynamic(Ball).BounceFactor := 0.75;
  164. GetOrCreateDCEDynamic(Ball).Friction := 0.1;
  165. GetOrCreateDCEDynamic(Ball).SlideOrBounce := csbBounce;
  166. GetOrCreateDCEDynamic(Ball).Size.Assign(Ball.Scale);
  167. end;
  168. //-----------------------------------------------------------------
  169. procedure TFormDCE.AddMushrooms;
  170. var
  171. i: Integer;
  172. proxy: TGLFreeFormProxy;
  173. S: TGLVector;
  174. f: Single;
  175. begin
  176. // spawn some more mushrooms using proxy objects
  177. for i := 0 to cNbMushrooms - 1 do
  178. begin
  179. // create a new proxy and set its MasterObject property
  180. proxy := TGLFreeFormProxy(Mushrooms.AddNewChild(TGLFreeFormProxy));
  181. proxy.ProxyOptions := [pooObjects];
  182. proxy.MasterObject := moMushroom;
  183. // retrieve reference attitude
  184. proxy.Direction := moMushroom.Direction;
  185. proxy.Up := moMushroom.Up;
  186. // randomize scale
  187. S := moMushroom.Scale.AsVector;
  188. f := (2 * Random + 1);
  189. ScaleVector(S, f);
  190. proxy.Scale.AsVector := S;
  191. // randomize position
  192. proxy.Position.SetPoint(Random(cSpread) - (cSpread / 2), moMushroom.Position.Z +
  193. 1.5 * f, Random(cSpread) - (cSpread / 2));
  194. // randomize orientation
  195. proxy.RollAngle := Random(360);
  196. proxy.TransformationChanged;
  197. GetOrCreateDCEStatic(proxy).Manager := GLDCEManager1;
  198. GetOrCreateDCEStatic(proxy).BounceFactor := 0.75;
  199. GetOrCreateDCEStatic(proxy).Friction := 10;
  200. GetOrCreateDCEStatic(proxy).Shape := csFreeform;
  201. end;
  202. end;
  203. //-----------------------------------------------------------------
  204. procedure TFormDCE.HandleKeys;
  205. var
  206. Force: TAffineVector;
  207. begin
  208. Force := NullVector;
  209. if IsKeyDown('w') or IsKeyDown('z') then
  210. Force.Z := cForce;
  211. if IsKeyDown('s') then
  212. Force.Z := -cForce;
  213. if IsKeyDown('a') or IsKeyDown('q') then
  214. Force.X := cForce;
  215. if IsKeyDown('d') or IsKeyDown('e') then
  216. Force.X := -cForce;
  217. GetOrCreateDCEDynamic(Player).ApplyAccel(Force);
  218. end;
  219. //-----------------------------------------------------------------
  220. procedure TFormDCE.HandleAnimation;
  221. var
  222. anim: string;
  223. begin
  224. if VectorNorm(GetOrCreateDCEDynamic(Player).Speed) > 0.1 then
  225. anim := 'run'
  226. else
  227. anim := 'stand';
  228. if Jumped then
  229. begin
  230. if (not GetOrCreateDCEDynamic(Player).InGround) then
  231. anim := 'jump'
  232. else
  233. Jumped := False;
  234. end;
  235. if anim = 'jump' then
  236. GLActor1.Interval := 500
  237. else
  238. GLActor1.Interval := 100;
  239. if GLActor1.CurrentAnimation <> anim then
  240. GLActor1.SwitchToAnimation(anim);
  241. end;
  242. //-----------------------------------------------------------------
  243. procedure TFormDCE.GLCadencer1Progress(Sender: TObject;
  244. const deltaTime, newTime: Double);
  245. begin
  246. HandleKeys;
  247. HandleAnimation;
  248. // This shows the manual progress, don't need this if you use the automatic mode
  249. if GLDCEManager1.ManualStep then
  250. GLDCEManager1.Step(deltaTime);
  251. Help.ModulateColor.Alpha := Help.ModulateColor.Alpha - (deltaTime * 0.05);
  252. if Help.ModulateColor.Alpha < 0.25 then
  253. Help.ModulateColor.Alpha := 0.25;
  254. HelpShadow.ModulateColor.Alpha := Help.ModulateColor.Alpha;
  255. HelpShadow.Text := Help.Text;
  256. HUDTextCoords.Text := 'X: ' + FloatToStrF(Player.Position.X, ffFixed, 7, 2) + ' ' +
  257. 'Y: ' + FloatToStrF(Player.Position.Y, ffFixed, 7, 2) + ' ' +
  258. 'Z: ' + FloatToStrF(Player.Position.Z, ffFixed, 7, 2);
  259. end;
  260. //-----------------------------------------------------------------
  261. procedure TFormDCE.GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
  262. X, Y: Integer);
  263. begin
  264. // Mouse look
  265. if ssLeft in Shift then
  266. begin
  267. GLCamera1.MoveAroundTarget((my - Y), 0);
  268. Player.Turn(-(mx - X));
  269. end;
  270. mx := X;
  271. my := Y;
  272. end;
  273. //-----------------------------------------------------------------
  274. procedure TFormDCE.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  275. var
  276. i: Integer;
  277. begin
  278. if Key = VK_F1 then
  279. AddBall;
  280. if Key = VK_F2 then
  281. for i := 1 to 10 do
  282. AddBall;
  283. if Key = VK_F3 then
  284. AddMushrooms;
  285. if (Key = VK_Space) then
  286. begin
  287. GetOrCreateDCEDynamic(Player).Jump(1, 20);
  288. Jumped := true;
  289. end;
  290. if Key = VK_F4 then
  291. begin
  292. Terrain.Visible := False;
  293. Ground.Visible := true;
  294. GetOrCreateDCEStatic(Terrain).Active := False;
  295. GetOrCreateDCEStatic(Ground).Active := true;
  296. end;
  297. if Key = VK_F5 then
  298. GLDCEManager1.ManualStep := not GLDCEManager1.ManualStep;
  299. if (Key = VK_RETURN) then
  300. begin
  301. Player.Position.SetPoint(0, 3, 0);
  302. Balls.DeleteChildren;
  303. Mushrooms.DeleteChildren;
  304. Help.ModulateColor.Alpha := 1;
  305. Terrain.Visible := true;
  306. Ground.Visible := False;
  307. GetOrCreateDCEStatic(Terrain).Active := true;
  308. GetOrCreateDCEStatic(Ground).Active := False;
  309. end;
  310. if Key = VK_ESCAPE then
  311. Halt;
  312. end;
  313. //-----------------------------------------------------------------
  314. procedure TFormDCE.PlayerBehaviours0Collision(Sender: TObject;
  315. ObjectCollided: TGLBaseSceneObject; CollisionInfo: TDCECollision);
  316. var
  317. v: TAffineVector;
  318. begin
  319. // Use some kind of identifier to know what object you are colliding
  320. // You can use the Tag, TagFloat, Name, Class
  321. if ObjectCollided.Tag = 1 then
  322. begin
  323. v := AffineVectorMake(VectorSubtract(ObjectCollided.AbsolutePosition, Player.AbsolutePosition));
  324. NormalizeVector(v);
  325. ScaleVector(v, 400);
  326. GetOrCreateDCEDynamic(ObjectCollided).StopAbsAccel;
  327. GetOrCreateDCEDynamic(ObjectCollided).ApplyAbsAccel(v);
  328. end;
  329. end;
  330. //-----------------------------------------------------------------
  331. procedure TFormDCE.GLDirectOpenGL1Render(Sender: TObject;
  332. var rci: TGLRenderContextInfo);
  333. var
  334. i: Integer;
  335. p, n: TAffineVector;
  336. begin
  337. // To use this you will need to enable the debug define in the
  338. // GLEllipseCollision.pas, if you do, don't forget to clear the
  339. // triangle list! -> SetLength(debug_tri,0);
  340. rci.GLStates.PointSize := 5.0;
  341. glColor3f(0, 1, 0);
  342. for i := 0 to High(debug_tri) do
  343. with debug_tri[i] do
  344. begin
  345. glColor3f(0, 0, 0);
  346. glBegin(GL_LINE_STRIP);
  347. glVertex3f(p1.X, p1.Y, p1.Z);
  348. glVertex3f(p2.X, p2.Y, p2.Z);
  349. glVertex3f(p3.X, p3.Y, p3.Z);
  350. glEnd;
  351. CalcPlaneNormal(p1, p2, p3, n);
  352. ScaleVector(n, 0.25);
  353. p.X := (p1.X + p2.X + p3.X) / 3;
  354. p.Y := (p1.Y + p2.Y + p3.Y) / 3;
  355. p.Z := (p1.Z + p2.Z + p3.Z) / 3;
  356. glColor3f(0, 0, 1);
  357. glBegin(GL_LINE_STRIP);
  358. glVertex3f(p.X, p.Y, p.Z);
  359. glVertex3f(p.X + n.X, p.Y + n.Y, p.Z + n.Z);
  360. glEnd;
  361. glBegin(GL_POINTS);
  362. glVertex3f(p.X + n.X, p.Y + n.Y, p.Z + n.Z);
  363. glEnd;
  364. end; // }
  365. SetLength(debug_tri, 0);
  366. end;
  367. //-----------------------------------------------------------------
  368. procedure TFormDCE.Timer1Timer(Sender: TObject);
  369. var
  370. S: string;
  371. begin
  372. if GLDCEManager1.ManualStep then
  373. S := 'Manual'
  374. else
  375. S := 'Automatic';
  376. GLHUDText1.Text := Format('FPS: %.1f - Dynamics: %d - Statics: %d - Step mode: %s',
  377. [GLSceneViewer1.FramesPerSecond, GLDCEManager1.DynamicCount, GLDCEManager1.StaticCount, S]);
  378. GLSceneViewer1.ResetPerformanceMonitor;
  379. end;
  380. end.