ElasticBody.h
上传用户:gb3593
上传日期:2022-01-07
资源大小:3028k
文件大小:16k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /*
  2. * Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty.  In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. * Permission is granted to anyone to use this software for any purpose,
  8. * including commercial applications, and to alter it and redistribute it
  9. * freely, subject to the following restrictions:
  10. * 1. The origin of this software must not be misrepresented; you must not
  11. * claim that you wrote the original software. If you use this software
  12. * in a product, an acknowledgment in the product documentation would be
  13. * appreciated but is not required.
  14. * 2. Altered source versions must be plainly marked as such, and must not be
  15. * misrepresented as being the original software.
  16. * 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #ifndef ELASTIC_BODY_H
  19. #define ELASTIC_BODY_H
  20. class ElasticBody : public Test
  21. {
  22. public:
  23. b2Body* bodies[64];
  24.     b2Body*  m_ground;
  25. b2Body*  m_elev;
  26. b2PrismaticJoint* m_joint_elev;
  27. /// Main...
  28. ElasticBody()
  29. {
  30. /// Bottom static body
  31. b2PolygonDef sd;
  32. sd.SetAsBox(50.0f, 2.0f);
  33. sd.friction = 0.1f;
  34. sd.restitution = 0.1f;
  35. b2BodyDef bd;
  36. bd.position.Set(-1.0f, -7.5f);
  37. m_ground = m_world->CreateBody(&bd);
  38. m_ground->CreateFixture(&sd);
  39. }
  40. /// Upper static body
  41. {
  42.             b2PolygonDef sd;
  43. sd.SetAsBox(20.0f, 0.50f,b2Vec2(0.f,0.f),0.047f*b2_pi);
  44. sd.friction    = 0.01f;
  45. sd.restitution = 0.001f;  
  46. b2BodyDef bd;
  47. bd.position.Set(-20.f, 93.0f);
  48. b2Body* g = m_world->CreateBody(&bd);
  49. g->CreateFixture(&sd);
  50. sd.SetAsBox(15.f, 0.50f,b2Vec2(-15.0f,12.5f),0.0f);
  51.             g->CreateFixture(&sd);
  52.             sd.SetAsBox(20.f,0.5f,b2Vec2(0.0f,-25.0f),-0.5f);
  53. g->CreateFixture(&sd);
  54.         }
  55. /// Left channel left wall
  56. {
  57.             b2PolygonDef sd;
  58. sd.SetAsBox(0.7f, 55.0f);
  59. sd.friction    = 0.1f;
  60. sd.restitution = 0.1f;  
  61. b2BodyDef bd;
  62. bd.position.Set(-49.3f, 50.0f);
  63. b2Body* g = m_world->CreateBody(&bd);
  64. g->CreateFixture(&sd);
  65.         }
  66. /// Right wall
  67. {
  68.             b2PolygonDef sd;
  69. sd.SetAsBox(0.7f, 55.0f);
  70. sd.friction    = 0.1f;
  71. sd.restitution = 0.1f;  
  72. b2BodyDef bd;
  73. bd.position.Set(45.f, 50.0f);
  74. b2Body* g = m_world->CreateBody(&bd);
  75. g->CreateFixture(&sd);
  76.         }
  77. /// Left channel right upper wall  
  78. {
  79.             b2PolygonDef sd;
  80. sd.SetAsBox(0.5f, 20.0f);
  81. sd.friction    = 0.05f;
  82. sd.restitution = 0.01f;  
  83. b2BodyDef bd;
  84. bd.position.Set(-42.0f, 70.0f);
  85.     bd.angle = -0.03f*b2_pi;
  86. b2Body* g = m_world->CreateBody(&bd);
  87. g->CreateFixture(&sd);
  88. }
  89. /// Left channel right lower wall
  90. {
  91.             b2PolygonDef sd;
  92. sd.SetAsBox(0.50f, 23.0f);
  93. sd.friction    = 0.05f;
  94. sd.restitution = 0.01f;  
  95. b2BodyDef bd;
  96. bd.position.Set(-44.0f, 27.0f);
  97. b2Body* g = m_world->CreateBody(&bd);
  98. g->CreateFixture(&sd);
  99.         /// Bottom motors
  100.     b2CircleDef cd;
  101. cd.radius   = 3.0f;
  102. cd.density  = 15.0f;
  103. cd.friction = 1.f;
  104. cd.restitution = 0.2f;
  105.         /// 1. 
  106. bd.position.Set(-40.0f,2.5f);
  107. b2Body* body = m_world->CreateBody(&bd);
  108. body->CreateFixture(&cd);
  109.             body->SetMassFromShapes(); 
  110.             b2RevoluteJointDef jr;
  111. jr.Initialize (g,body,body->GetWorldCenter()+b2Vec2(0.f,1.f));
  112.             jr.maxMotorTorque = 30000.f;
  113.             jr.enableMotor    = true; 
  114.             jr.motorSpeed     = 20.f;
  115. m_world->CreateJoint(&jr);
  116.         /// 1. left down
  117. bd.position.Set(-46.0f,-2.5f);
  118.             cd. radius = 1.5f;  jr.motorSpeed  = -20.f;
  119. body = m_world->CreateBody(&bd);
  120. body->CreateFixture(&cd);
  121.             sd.SetAsBox(2.0f, 0.50f);
  122.             body->CreateFixture(&sd);
  123.             body->SetMassFromShapes(); 
  124. jr.Initialize (g,body,body->GetWorldCenter());
  125. m_world->CreateJoint(&jr);
  126.         /// 2.
  127.             cd.radius   = 3.0f; jr.motorSpeed  = 20.f;
  128. bd.position.Set(-32.0f,2.5f);
  129. body = m_world->CreateBody(&bd);
  130. body->CreateFixture(&cd);
  131.             body->SetMassFromShapes(); 
  132. jr.Initialize (g,body,body->GetWorldCenter()+b2Vec2(0.f,1.f));
  133. m_world->CreateJoint(&jr);
  134.         /// 3.
  135.             jr.motorSpeed     = 20.f;
  136. bd.position.Set(-24.0f,1.5f);
  137. body = m_world->CreateBody(&bd);
  138. body->CreateFixture(&cd);
  139.             body->SetMassFromShapes(); 
  140. jr.Initialize (g,body,body->GetWorldCenter()+b2Vec2(0.f,1.f));
  141. m_world->CreateJoint(&jr);
  142.         /// 4.
  143. bd.position.Set(-16.0f,0.8f);
  144. body = m_world->CreateBody(&bd);
  145. body->CreateFixture(&cd);
  146.             body->SetMassFromShapes(); 
  147. jr.Initialize (g,body,body->GetWorldCenter()+b2Vec2(0.f,1.f));
  148. m_world->CreateJoint(&jr);
  149.         /// 5.
  150. bd.position.Set(-8.0f,0.5f);
  151. body = m_world->CreateBody(&bd);
  152. body->CreateFixture(&cd);
  153.             body->SetMassFromShapes(); 
  154. jr.Initialize (g,body,body->GetWorldCenter()+b2Vec2(0.f,1.f));
  155. m_world->CreateJoint(&jr);
  156.         /// 6.
  157. bd.position.Set(0.0f,0.1f);
  158. body = m_world->CreateBody(&bd);
  159. body->CreateFixture(&cd);
  160.             body->SetMassFromShapes(); 
  161. jr.Initialize (g,body,body->GetWorldCenter()+b2Vec2(0.f,1.f));
  162. m_world->CreateJoint(&jr);
  163.         /// 7.
  164. bd.position.Set(8.0f,-0.5f);
  165. body = m_world->CreateBody(&bd);
  166. body->CreateFixture(&cd);
  167. sd.SetAsBox(3.7f, 0.5f);
  168. body->CreateFixture(&sd);
  169.             body->SetMassFromShapes(); 
  170. jr.Initialize (g,body,body->GetWorldCenter()+b2Vec2(0.f,1.f));
  171. m_world->CreateJoint(&jr);
  172.         /// 8. right rotator
  173.             sd.SetAsBox(5.f, 0.5f);
  174.             sd.density = 2.0f;
  175. bd.position.Set(18.0f,1.f);
  176. b2Body* rightmotor = m_world->CreateBody(&bd);
  177. rightmotor->CreateFixture(&sd);
  178. sd.SetAsBox(4.5f, 0.5f, b2Vec2(0.f,0.f),b2_pi/3.f);
  179. rightmotor->CreateFixture(&sd);
  180. sd.SetAsBox(4.5f, 0.5f, b2Vec2(0.f,0.f),b2_pi*2.f/3.f);
  181. rightmotor->CreateFixture(&sd);
  182. cd.radius = 4.2f;
  183. rightmotor->CreateFixture(&cd);
  184.             rightmotor->SetMassFromShapes(); 
  185. jr.Initialize (g,rightmotor,rightmotor->GetWorldCenter());
  186.             jr.maxMotorTorque = 70000.f;
  187.             jr.motorSpeed     = -4.f;
  188.             m_world->CreateJoint(&jr);
  189.         /// 9. left rotator
  190.             sd.SetAsBox(8.5f, 0.5f);
  191.             sd.density = 2.0f;
  192. bd.position.Set(-34.0f,17.f);
  193. body = m_world->CreateBody(&bd);
  194. body->CreateFixture(&sd);
  195. sd.SetAsBox(8.5f, 0.5f, b2Vec2(0.f,0.f),b2_pi*.5f);
  196. body->CreateFixture(&sd);
  197. cd.radius = 7.f;
  198. cd.friction = 0.9f;
  199. body->CreateFixture(&cd);
  200.             body->SetMassFromShapes(); 
  201. jr.Initialize (g,body,body->GetWorldCenter());
  202.             jr.maxMotorTorque = 100000.f;
  203.             jr.motorSpeed     = -5.f;            
  204.             m_world->CreateJoint(&jr);
  205.         /// big compressor
  206.             sd.SetAsBox(3.0f,4.f);
  207.             sd.density = 10.0f;
  208. bd.position.Set(-16.0f,17.f);
  209. b2Body *hammerleft = m_world->CreateBody(&bd);
  210. hammerleft->CreateFixture(&sd);
  211. hammerleft->SetMassFromShapes();
  212. b2DistanceJointDef jd;
  213. jd.Initialize(body, hammerleft, body->GetWorldCenter()+b2Vec2(0.f,6.f), hammerleft->GetWorldCenter() );
  214. m_world->CreateJoint(&jd);
  215. bd.position.Set(4.0f,17.f);
  216. b2Body *hammerright = m_world->CreateBody(&bd);
  217. hammerright->CreateFixture(&sd);
  218. hammerright->SetMassFromShapes();
  219. jd.Initialize(body, hammerright, body->GetWorldCenter()-b2Vec2(0.f,6.f), hammerright->GetWorldCenter() );
  220. m_world->CreateJoint(&jd);
  221.             /// pusher
  222.             sd.SetAsBox(6.f,0.75f);
  223. bd.position.Set(-21.0f,9.f);
  224. b2Body* pusher = m_world->CreateBody(&bd);
  225. pusher->CreateFixture(&sd);
  226. sd.SetAsBox(2.f,1.5f,b2Vec2(-5.f,0.f),0.f);
  227. pusher->SetMassFromShapes();
  228. pusher->CreateFixture(&sd);
  229. jd.Initialize(rightmotor,pusher,rightmotor->GetWorldCenter()+b2Vec2(-8.0f,0.f),
  230.           pusher->GetWorldCenter()+b2Vec2(5.0f,0.f) );
  231. m_world->CreateJoint(&jd);
  232.         }
  233.         /// Static bodies above motors
  234.        {
  235.             b2PolygonDef sd;
  236. b2CircleDef  cd;
  237. sd.SetAsBox(9.0f, 0.5f);
  238. sd.friction    = 0.05f;
  239. sd.restitution = 0.01f;  
  240. b2BodyDef bd;
  241. bd.position.Set(-15.5f, 12.f);
  242.             bd.angle = 0.0;
  243. b2Body* g = m_world->CreateBody(&bd);
  244. g->CreateFixture(&sd);
  245.     
  246. sd.SetAsBox(8.f, 0.5f, b2Vec2(23.f,0.f),0.f);
  247. g->CreateFixture(&sd);
  248.             /// compressor statics  
  249. sd.SetAsBox(7.0f, 0.5f, b2Vec2(-2.f,9.f),0.f);
  250. g->CreateFixture(&sd);
  251. sd.SetAsBox(9.0f, 0.5f, b2Vec2(22.f,9.f),0.f);
  252. g->CreateFixture(&sd);
  253. sd.SetAsBox(19.0f, 0.5f, b2Vec2(-9.f,15.f),-0.05f);
  254. g->CreateFixture(&sd);
  255. sd.SetAsBox(4.7f, 0.5f, b2Vec2(15.f,11.5f),-0.5f);
  256. g->CreateFixture(&sd);
  257.             /// below compressor
  258. sd.SetAsBox(26.0f, 0.3f, b2Vec2(17.f,-4.4f),-0.02f);
  259. g->CreateFixture(&sd);
  260. cd.radius   = 1.0f; cd.friction = 1.0;
  261. cd.localPosition = b2Vec2(29.f,-6.f);
  262.             g->CreateFixture(&cd); 
  263.             cd.radius   = 0.7f;
  264. cd.localPosition = b2Vec2(-2.f,-4.5f);
  265.             g->CreateFixture(&cd);
  266.         }
  267.         /// Elevator
  268.         {
  269.             b2BodyDef  bd;
  270.             b2CircleDef cd;
  271.             b2PolygonDef sd;
  272. bd.position.Set(40.0f,4.0f);
  273. m_elev = m_world->CreateBody(&bd);
  274. sd.SetAsBox(0.5f, 2.5f,b2Vec2(3.0f,-3.0f), 0.f);
  275. sd.density     = 1.f;
  276. sd.friction    = 0.01f;
  277. m_elev->CreateFixture(&sd);
  278. sd.SetAsBox(7.0f, 0.5f, b2Vec2(-3.5f,-5.5f), 0.f);
  279. m_elev->CreateFixture(&sd);
  280. sd.SetAsBox(0.5f, 2.5f, b2Vec2(-11.f,-3.5f), 0.f);
  281. m_elev->CreateFixture(&sd);
  282.             m_elev->SetMassFromShapes();           
  283.     
  284. b2PrismaticJointDef jp;
  285. jp.Initialize(m_ground,m_elev, bd.position, b2Vec2(0.0f, 1.0f));
  286. jp.lowerTranslation =  0.0f;
  287. jp.upperTranslation = 100.0f;
  288. jp.enableLimit = true;
  289. jp.enableMotor = true;
  290. jp.maxMotorForce = 10000.f;
  291. jp.motorSpeed    = 0.f; 
  292. m_joint_elev = (b2PrismaticJoint*)m_world->CreateJoint(&jp);   
  293.             
  294. /// Korb
  295.             sd.SetAsBox(2.3f, 0.5f,b2Vec2(1.f,0.0f), 0.0f);
  296.             sd.density = 0.5f;
  297.             bd.position.Set(29.0f,6.5f);
  298. b2Body* body = m_world->CreateBody(&bd);
  299. body->CreateFixture(&sd);
  300.             sd.SetAsBox(2.5f, 0.5f,b2Vec2(3.0f,-2.f), b2_pi/2.f);
  301.             body->CreateFixture(&sd);
  302.             sd.SetAsBox(4.6f, 0.5f,b2Vec2(7.8f,-4.0f), 0.f);
  303.             body->CreateFixture(&sd);
  304.             sd.SetAsBox(0.5f, 4.5f,b2Vec2(12.f,0.0f), 0.f);
  305.             body->CreateFixture(&sd);
  306.             
  307. sd.SetAsBox(0.5f, 0.5f,b2Vec2(13.f,4.0f), 0.f);
  308.             body->CreateFixture(&sd);
  309.             cd.radius   = 0.7f; cd.density  = 1.f; cd.friction = 0.01f;
  310.             cd.localPosition = b2Vec2(0.f,0.f);
  311.             body->CreateFixture(&cd);
  312.             body->SetMassFromShapes();  
  313.             b2RevoluteJointDef jr;
  314.             jr.Initialize(m_elev,body, bd.position);
  315.             jr.enableLimit = true;
  316.             jr.lowerAngle  = -0.2f;
  317.             jr.upperAngle  = b2_pi*1.1f;
  318.             jr.collideConnected = true;
  319.             m_world->CreateJoint(&jr);
  320.             /// upper body exit
  321.             sd.SetAsBox(14.0f, 0.5f,b2Vec2(-3.5f,-10.0f), 0.0f);
  322.             bd.position.Set(17.5f,96.0f);
  323.             body = m_world->CreateBody(&bd);
  324.             body->CreateFixture(&sd);
  325. }
  326. /// "Elastic body" 64 bodies - something like a lin. elastic compound
  327. /// connected via dynamic forces (springs) 
  328. {
  329. b2PolygonDef sd;
  330. sd.SetAsBox(0.55f, 0.55f);
  331. sd.density    = 1.5f;
  332. sd.friction   = 0.01f;
  333. sd.filter.groupIndex = -1;
  334. b2Vec2       startpoint(30.f,20.f);
  335. b2BodyDef    bd;
  336. bd.isBullet   = false;
  337.          bd.allowSleep = false;
  338. for (int i = 0; i < 8; ++i) 
  339.             {
  340. for (int j = 0; j < 8; ++j) 
  341.                 {
  342. bd.position.Set(j*1.02f, 2.51f + 1.02f * i);
  343. bd.position  += startpoint;
  344. b2Body* body  = m_world->CreateBody(&bd);
  345. bodies[8*i+j] = body;
  346. body->CreateFixture(&sd);
  347. body->SetMassFromShapes();
  348. }
  349. }
  350. }
  351. }
  352. ///  Apply dynamic forces (springs) and check elevator state
  353. void Step(Settings* settings)
  354. {
  355. Test::Step(settings);
  356. for (int i=0; i<8; ++i){
  357. for (int j=0; j<8; ++j){
  358. b2Vec2 zero(0.0f,0.0f);
  359. b2Vec2 down(0.0f, -0.5f);
  360. b2Vec2 up(0.0f, 0.5f);
  361. b2Vec2 right(0.5f, 0.0f);
  362. b2Vec2 left(-0.5f, 0.0f);
  363. int ind = i*8+j;
  364. int indr = ind+1;
  365. int indd = ind+8;
  366. float32 spring = 500.0f;
  367. float32 damp = 5.0f;
  368. if (j<7) {
  369. AddSpringForce(*(bodies[ind]),zero,*(bodies[indr]),zero,spring, damp, 1.0f);
  370. AddSpringForce(*(bodies[ind]),right,*(bodies[indr]),left,0.5f*spring, damp, 0.0f);
  371. }
  372. if (i<7) {
  373. AddSpringForce(*(bodies[ind]),zero,*(bodies[indd]),zero,spring, damp, 1.0f);
  374. AddSpringForce(*(bodies[ind]),up,*(bodies[indd]),down,0.5f*spring,damp,0.0f);
  375. }
  376. int inddr = indd + 1;
  377. int inddl = indd - 1;
  378. float32 drdist = sqrtf(2.0f);
  379. if (i < 7 && j < 7){
  380. AddSpringForce(*(bodies[ind]),zero,*(bodies[inddr]),zero,spring, damp, drdist);
  381. }
  382. if (i < 7 && j > 0){
  383. AddSpringForce(*(bodies[ind]),zero,*(bodies[inddl]),zero,spring, damp, drdist);
  384. }
  385. indr = ind+2;
  386. indd = ind+8*2;
  387. if (j<6) {
  388. AddSpringForce(*(bodies[ind]),zero,*(bodies[indr]),zero,spring, damp, 2.0f);
  389. }
  390. if (i<6) {
  391. AddSpringForce(*(bodies[ind]),zero,*(bodies[indd]),zero,spring,damp,2.0f);
  392. }
  393. inddr = indd + 2;
  394. inddl = indd - 2;
  395. drdist = sqrtf(2.0f)*2.0f;
  396. if (i < 6 && j < 6){
  397. AddSpringForce(*(bodies[ind]),zero,*(bodies[inddr]),zero,spring, damp, drdist);
  398. }
  399. if (i < 6 && j > 1){
  400. AddSpringForce(*(bodies[ind]),zero,*(bodies[inddl]),zero,spring, damp, drdist);
  401. }
  402. }
  403. }
  404. /// Check if bodies are near elevator
  405. ///  Look if the body to lift is near the elevator
  406. b2Vec2 p1 = bodies[0]->GetWorldCenter(); 
  407.         b2Vec2 p2 = bodies[63]->GetWorldCenter(); 
  408. ///    m_elev:   elevator prism. joint
  409. b2Vec2 e = m_elev->GetWorldCenter() + b2Vec2(0.f,7.f);  
  410. // maybe not the best way to do it...
  411. // Bodies reached the elevator side 
  412. if ( p1.x>e.x || p2.x>e.x ) {
  413.        // go up
  414. if ( ( p1.y<e.y || p2.y<e.y ) &&
  415.  ( m_joint_elev->GetJointTranslation()<=m_joint_elev->GetLowerLimit()+1.f ) ) 
  416. {
  417. m_joint_elev->SetMotorSpeed(20.f);
  418.                 //printf("lift goes up trans: %Gn",m_joint_elev->GetJointTranslation());
  419. }
  420. }
  421. // go down
  422. if ( (m_joint_elev->GetJointTranslation()>=m_joint_elev->GetUpperLimit()-2.f) ) 
  423. {
  424.                m_joint_elev->SetMotorSpeed(-15.f);
  425.                //printf("lift goes down: %Gn",m_joint_elev->GetJointTranslation());
  426. }
  427. }
  428.    /// Add a spring force
  429.    void AddSpringForce(b2Body& bA, b2Vec2& localA, b2Body& bB, b2Vec2& localB, float32 k, float32 friction, float32 desiredDist)
  430.    {
  431.         b2Vec2 pA = bA.GetWorldPoint(localA);
  432.         b2Vec2 pB = bB.GetWorldPoint(localB);
  433.         b2Vec2 diff = pB - pA;
  434.         //Find velocities of attach points
  435.         b2Vec2 vA = bA.GetLinearVelocity() - b2Cross(bA.GetWorldVector(localA), bA.GetAngularVelocity());
  436.         b2Vec2 vB = bB.GetLinearVelocity() - b2Cross(bB.GetWorldVector(localB), bB.GetAngularVelocity());
  437.         b2Vec2 vdiff = vB-vA;
  438.         float32 dx = diff.Normalize(); //normalizes diff and puts length into dx
  439.         float32 vrel = vdiff.x*diff.x + vdiff.y*diff.y;
  440.         float32 forceMag = -k*(dx-desiredDist) - friction*vrel;
  441.         diff *= forceMag; // diff *= forceMag
  442.         bB.ApplyForce(diff, bA.GetWorldPoint(localA));
  443.         diff *= -1.0f;
  444.         bA.ApplyForce(diff, bB.GetWorldPoint(localB));
  445.     }
  446.     /// Default constructor
  447. static Test* Create()
  448. {
  449. return new ElasticBody;
  450. }
  451. };
  452. #endif