fOdeFurballC.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #include <stdlib.h>
  4. #include <math.hpp>
  5. #pragma hdrstop
  6. #include "fOdeFurballC.h"
  7. #pragma link "Stage.VectorGeometry"
  8. #pragma link "Stage.Keyboard"
  9. #pragma link "GLS.ODEManager"
  10. #pragma link "GLS.Navigator"
  11. #pragma link "GLS.ShadowPlane"
  12. #pragma link "GLS.Extrusion"
  13. #pragma link "GLS.Texture"
  14. #pragma link "GLS.Cadencer"
  15. #pragma link "GLS.Objects"
  16. #pragma link "GLS.Scene"
  17. #pragma link "GLS.SceneViewer"
  18. #pragma link "GLS.VerletTypes"
  19. //---------------------------------------------------------------------------
  20. #pragma package(smart_init)
  21. //---------------------------------------------------------------------------
  22. #pragma link "GLS.BaseClasses"
  23. #pragma link "GLS.Coordinates"
  24. #pragma resource "*.dfm"
  25. TFormFurBall *FormFurBall;
  26. //---------------------------------------------------------------------------
  27. float random(void)
  28. {
  29. return (float)(rand() & 0xFFF) / (float)0xFFF;
  30. }
  31. //---------------------------------------------------------------------------
  32. void __cdecl nearCallback(void *data, PdxGeom o1, PdxGeom o2)
  33. {
  34. const int cCOL_MAX = 1;
  35. int i, numc;
  36. PdxBody b1, b2;
  37. TdContact contact[cCOL_MAX];
  38. TdJointID c;
  39. // exit without doing anything if the two bodies are connected by a joint
  40. b1 = dGeomGetBody(o1);
  41. b2 = dGeomGetBody(o2);
  42. if(b1 && b2 && (dAreConnected(b1, b2) != 0))
  43. return;
  44. for(i = 0; i <= cCOL_MAX - 1; i++)
  45. {
  46. contact[i].surface.mode = dContactBounce;
  47. // This determines friction, play around with it!
  48. contact[i].surface.mu = 3; //10e9; //dInfinity; SHOULD BE INFINITY!
  49. contact[i].surface.mu2 = 0;
  50. contact[i].surface.bounce = 0.5;
  51. contact[i].surface.bounce_vel = 0.1;
  52. }
  53. numc = dCollide(o1, o2, cCOL_MAX, contact[0].geom, sizeof(TdContact));
  54. if(numc > 0)
  55. {
  56. for(i = 0; i <= numc - 1; i++)
  57. {
  58. c = dJointCreateContact(FormFurBall->world, FormFurBall->contactgroup, &contact[i]);
  59. dJointAttach(c, b1, b2);
  60. }
  61. }
  62. }
  63. //---------------------------------------------------------------------------
  64. __fastcall TFormFurBall::TFormFurBall(TComponent* Owner)
  65. : TForm(Owner)
  66. {
  67. }
  68. //---------------------------------------------------------------------------
  69. const float cOffset = 0.03;
  70. void __fastcall TFormFurBall::FormCreate(TObject *Sender)
  71. {
  72. Show();
  73. Randomize();
  74. world = dWorldCreate();
  75. space = dHashSpaceCreate(NULL);
  76. contactgroup = dJointGroupCreate (1000000);
  77. dWorldSetGravity (world,0,0,-9.81);
  78. CreateODEPlaneFromGLPlane(GLShadowPlane_Floor, space);
  79. CreateODEPlaneFromGLPlane(GLShadowPlane_Floor2, space);
  80. CreateODEPlaneFromGLPlane(GLShadowPlane_Wall, space);
  81. CreateODEPlaneFromGLPlane(GLShadowPlane_Wall2, space);
  82. CreateODEPlaneFromGLPlane(GLShadowPlane_Wall3, space);
  83. // dCreatePlane (space,0,0,1,0);
  84. VerletWorld = new TGLVerletWorld;
  85. VerletWorld->Iterations = 2;
  86. VerletWorld->VerletNodeClass = __classid(TGLVerletNode);
  87. CheckBox_FurGravityClick(Sender);
  88. CheckBox_WindResistenceClick(Sender);
  89. CreateVerletPlaneFromGLPlane(GLShadowPlane_Floor, VerletWorld, cOffset);
  90. CreateVerletPlaneFromGLPlane(GLShadowPlane_Floor2, VerletWorld, cOffset);
  91. CreateVerletPlaneFromGLPlane(GLShadowPlane_Wall, VerletWorld, cOffset);
  92. CreateVerletPlaneFromGLPlane(GLShadowPlane_Wall2, VerletWorld, cOffset);
  93. CreateVerletPlaneFromGLPlane(GLShadowPlane_Wall3, VerletWorld, cOffset);
  94. HairList = new TList;
  95. CreateBall();
  96. }
  97. //---------------------------------------------------------------------------
  98. void __fastcall TFormFurBall::FormClose(TObject *Sender, TCloseAction &Action)
  99. {
  100. GLCadencer1->Enabled = false;
  101. dJointGroupDestroy(contactgroup);
  102. dSpaceDestroy(space);
  103. dWorldDestroy(world);
  104. CloseODE();
  105. }
  106. //---------------------------------------------------------------------------
  107. double angle = 0;
  108. void __fastcall TFormFurBall::GLCadencer1Progress(TObject *Sender, const double deltaTime,
  109. const double newTime)
  110. {
  111. const float cTIME_STEP = 0.01;
  112. int i, j;
  113. float Delta;
  114. TGLVerletHair *Hair;
  115. TGLLines *GLLines;
  116. Delta = deltaTime;
  117. angle = angle + Delta * 3;
  118. while(PhysicsTime < newTime)
  119. {
  120. PhysicsTime = PhysicsTime + cTIME_STEP;
  121. if(!CheckBox_LockBall->Checked)
  122. {
  123. dSpaceCollide(space, NULL, nearCallback);
  124. dWorldStep(world, cTIME_STEP); //}
  125. // remove all contact joints
  126. dJointGroupEmpty(contactgroup);
  127. if(IsKeyDown(VK_UP))
  128. dBodyAddForce(odeFurBallBody, 0, 0, 2.5);
  129. else if(IsKeyDown(VK_DOWN))
  130. dBodyAddForce(odeFurBallBody, 0, 0, -2.5);
  131. if(IsKeyDown('A'))
  132. dBodyAddForce(odeFurBallBody, 0, -1, 0);
  133. else if(IsKeyDown('D'))
  134. dBodyAddForce(odeFurBallBody, 0, 1, 0);
  135. if(IsKeyDown('W'))
  136. dBodyAddForce(odeFurBallBody, -1, 0, 0);
  137. else if(IsKeyDown('S'))
  138. dBodyAddForce(odeFurBallBody, 1, 0, 0);
  139. }
  140. PositionSceneObject(FurBall, odeFurBallGeom);
  141. VCSphere->Location = FurBall->Position->AsAffineVector;
  142. VerletWorld->Progress(cTIME_STEP, PhysicsTime);
  143. }
  144. for(i = 0; i <= HairList->Count - 1; i++)
  145. {
  146. Hair = (TGLVerletHair *) HairList->Items[i];
  147. GLLines = (TGLLines *) Hair->Data;
  148. for(j = 1; j <= Hair->NodeList->Count - 1; j++)
  149. GLLines->Nodes->Items[j - 1]->AsAffineVector =
  150. Hair->NodeList->Items[j]->Location;
  151. }
  152. }
  153. //---------------------------------------------------------------------------
  154. void __fastcall TFormFurBall::DC_LightHolderProgress(TObject *Sender, const double deltaTime,
  155. const double newTime)
  156. {
  157. DC_LightHolder->Roll(deltaTime*M_PI*2*8);
  158. }
  159. //---------------------------------------------------------------------------
  160. void __fastcall TFormFurBall::GLSceneViewer1MouseMove(TObject *Sender, TShiftState Shift,
  161. int X, int Y)
  162. {
  163. if (Shift.Contains(ssLeft))
  164. GLCamera1->MoveAroundTarget(mY-Y, mX-X);
  165. mX = X;
  166. mY = Y;
  167. }
  168. //---------------------------------------------------------------------------
  169. const int cRadiusMultiplier = 5, cSegmentCount = 4, cHairCount =
  170. 200, cRootDepth = 4;
  171. void __fastcall TFormFurBall::CreateRandomHair()
  172. {
  173. int i;
  174. TAffineVector Dir;
  175. TGLVerletHair *Hair;
  176. TGLLines *GLLines;
  177. Dir = AffineVectorMake(random() - 0.5, random() - 0.5, random() - 0.5);
  178. NormalizeVector(Dir);
  179. TGLStiffnessSetVH vhs;
  180. vhs << vhsSkip1Node;
  181. Hair =
  182. new TGLVerletHair(VerletWorld, FurBall->Radius * cRootDepth,
  183. FurBall->Radius * cRadiusMultiplier, cSegmentCount,
  184. VectorAdd(AffineVectorMake(FurBall->AbsolutePosition),
  185. VectorScale(Dir, FurBall->Radius)), Dir, vhs);
  186. GLLines = (TGLLines *) (DCShadowCaster->AddNewChild(__classid(TGLLines)));
  187. GLLines->NodesAspect = lnaInvisible;
  188. GLLines->LineWidth = 2;
  189. GLLines->LineColor->Color = clrBlack;
  190. for(i = 0; i <= Hair->NodeList->Count - 1; i++)
  191. ((TGLVerletNode *) Hair->NodeList->Items[i])->GLBaseSceneObject = FurBall;
  192. for(i = 1; i <= Hair->NodeList->Count - 1; i++)
  193. GLLines->AddNode(Hair->NodeList->Items[i]->Location);
  194. for(i = 0; i <= GLLines->Nodes->Count - 1; i++)
  195. ((TGLLinesNode *) GLLines->Nodes->Items[i])->Color->Color = clrBlack;
  196. GLLines->ObjectStyle = GLLines->ObjectStyle << osDirectDraw;
  197. GLLines->SplineMode = lsmCubicSpline;
  198. Hair->Data = GLLines;
  199. HairList->Add(Hair);
  200. }
  201. //---------------------------------------------------------------------------
  202. void __fastcall TFormFurBall::CreateFur()
  203. {
  204. TGLVerletHair *Hair;
  205. int i;
  206. for(i = 0; i <= HairList->Count - 1; i++)
  207. {
  208. Hair = ((TGLVerletHair *) HairList->Items[i]);
  209. delete((TGLLines *) Hair->Data);
  210. delete Hair;
  211. }
  212. HairList->Clear();
  213. for(i = 0; i <= cHairCount - 1; i++)
  214. CreateRandomHair();
  215. }
  216. //---------------------------------------------------------------------------
  217. void __fastcall TFormFurBall::CreateBall()
  218. {
  219. TdMass m;
  220. dMassSetSphere(m, 1, FurBall->Radius);
  221. odeFurBallGeom = dCreateSphere(space, FurBall->Radius);
  222. odeFurBallBody = dBodyCreate(world);
  223. dGeomSetBody(odeFurBallGeom, odeFurBallBody);
  224. dBodySetMass(odeFurBallBody, &m);
  225. dBodySetLinearVel(odeFurBallBody, 0, 14, 0);
  226. dBodyAddTorque(odeFurBallBody, 0.1, 0.1, 0.1);
  227. // Add the GLScene object
  228. odeFurBallGeom->data = FurBall;
  229. CopyPosFromGeomToGL(odeFurBallGeom, FurBall);
  230. VCSphere = new TGLVerletFrictionSphere(VerletWorld);
  231. VCSphere->Radius = FurBall->Radius * 1.1;
  232. VCSphere->Location = AffineVectorMake(FurBall->AbsolutePosition);
  233. CreateFur();
  234. }
  235. //---------------------------------------------------------------------------
  236. void __fastcall TFormFurBall::CheckBox_FurGravityClick(TObject *Sender)
  237. {
  238. if(!CheckBox_FurGravity->Checked)
  239. delete Gravity;
  240. else
  241. {
  242. Gravity = new TGLVerletGravity(VerletWorld);
  243. Gravity->Gravity = AffineVectorMake(0, 0, -9.81);
  244. }
  245. }
  246. //---------------------------------------------------------------------------
  247. const float cMaxWindMag = 8;
  248. void __fastcall TFormFurBall::CheckBox_WindResistenceClick(TObject *Sender)
  249. {
  250. if(!CheckBox_WindResistence->Checked)
  251. delete AirResistance;
  252. else
  253. {
  254. AirResistance = new TGLVerletAirResistance(VerletWorld);
  255. AirResistance->DragCoeff = 0.01;
  256. AirResistance->WindDirection = AffineVectorMake(1, 0, 0);
  257. AirResistance->WindMagnitude =
  258. (float)(TrackBar_WindForce->Position) / 100.0 * cMaxWindMag;
  259. AirResistance->WindChaos = 0.4;
  260. }
  261. TrackBar_WindForce->Enabled = CheckBox_WindResistence->Checked;
  262. }
  263. //---------------------------------------------------------------------------
  264. void __fastcall TFormFurBall::TrackBar_WindForceChange(TObject *Sender)
  265. {
  266. if(AirResistance)
  267. AirResistance->WindMagnitude =
  268. (float)(TrackBar_WindForce->Position) / 100.0 * cMaxWindMag;
  269. }
  270. //---------------------------------------------------------------------------
  271. void __fastcall TFormFurBall::CheckBox_BaldClick(TObject *Sender)
  272. {
  273. for(int i = 0; i <= HairList->Count - 1; i++)
  274. {
  275. TGLVerletHair *h = (TGLVerletHair *) (HairList->Items[i]);
  276. {
  277. h->Anchor->NailedDown = !CheckBox_Bald->Checked;
  278. h->Anchor->OldLocation = h->Anchor->Location;
  279. h->Root->NailedDown = !CheckBox_Bald->Checked;
  280. h->Root->OldLocation = h->Root->Location;
  281. }
  282. }
  283. if(!CheckBox_Bald->Checked)
  284. VerletWorld->PauseInertia(5);
  285. }
  286. //---------------------------------------------------------------------------
  287. void __fastcall TFormFurBall::Timer1Timer(TObject *Sender)
  288. {
  289. Label_FPS->Caption = GLSceneViewer1->FramesPerSecondText(1);
  290. GLSceneViewer1->ResetPerformanceMonitor();
  291. }
  292. //---------------------------------------------------------------------------
  293. void __fastcall TFormFurBall::CheckBox_ShadowsClick(TObject *Sender)
  294. {
  295. TGLLightSource *light;
  296. if(CheckBox_Shadows->Checked)
  297. light = GLLightSource1;
  298. else
  299. light = NULL;
  300. GLShadowPlane_Floor->ShadowedLight = light;
  301. GLShadowPlane_Floor2->ShadowedLight = light;
  302. GLShadowPlane_Wall->ShadowedLight = light;
  303. GLShadowPlane_Wall2->ShadowedLight = light;
  304. GLShadowPlane_Wall3->ShadowedLight = light;
  305. }
  306. //---------------------------------------------------------------------------
  307. void __fastcall TFormFurBall::CheckBox_InertiaClick(TObject *Sender)
  308. {
  309. VerletWorld->Inertia = CheckBox_Inertia->Checked;
  310. }
  311. //---------------------------------------------------------------------------
  312. void __fastcall TFormFurBall::FormMouseWheel(TObject *Sender, TShiftState Shift, int WheelDelta,
  313. TPoint &MousePos, bool &Handled)
  314. {
  315. GLCamera1-> AdjustDistanceToTarget(Power(1.1, WheelDelta / 120.0));
  316. }
  317. //---------------------------------------------------------------------------