fDceDemoD.pas 12 KB

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