b2BuoyancyController.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * Copyright (c) 2006-2007 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. #include "b2BuoyancyController.h"
  19. b2BuoyancyController::b2BuoyancyController(const b2BuoyancyControllerDef* def) : b2Controller(def)
  20. {
  21. normal = def->normal;
  22. offset = def->offset;
  23. density = def->density;
  24. velocity = def->velocity;
  25. linearDrag = def->linearDrag;
  26. angularDrag = def->angularDrag;
  27. useDensity = def->useDensity;
  28. useWorldGravity = def->useWorldGravity;
  29. gravity = def->gravity;
  30. }
  31. void b2BuoyancyController::Step(const b2TimeStep& step)
  32. {
  33. B2_NOT_USED(step);
  34. if(!m_bodyList)
  35. return;
  36. if(useWorldGravity){
  37. gravity = m_world->GetGravity();
  38. }
  39. for(b2ControllerEdge *i=m_bodyList;i;i=i->nextBody){
  40. b2Body* body = i->body;
  41. if(body->IsSleeping()){
  42. //Buoyancy force is just a function of position,
  43. //so unlike most forces, it is safe to ignore sleeping bodes
  44. continue;
  45. }
  46. b2Vec2 areac(0,0);
  47. b2Vec2 massc(0,0);
  48. float32 area = 0;
  49. float32 mass = 0;
  50. for(b2Shape* shape=body->GetShapeList();shape;shape=shape->GetNext()){
  51. b2Vec2 sc(0,0);
  52. float32 sarea = shape->ComputeSubmergedArea(normal,offset,body->GetXForm(),&sc);
  53. area += sarea;
  54. areac.x += sarea * sc.x;
  55. areac.y += sarea * sc.y;
  56. float shapeDensity = 0;
  57. if(useDensity){
  58. //TODO: Expose density publicly
  59. shapeDensity=shape->GetDensity();
  60. }else{
  61. shapeDensity = 1;
  62. }
  63. mass += sarea*shapeDensity;
  64. massc.x += sarea * sc.x * shapeDensity;
  65. massc.y += sarea * sc.y * shapeDensity;
  66. }
  67. areac.x/=area;
  68. areac.y/=area;
  69. b2Vec2 localCentroid = b2MulT(body->GetXForm(),areac);
  70. massc.x/=mass;
  71. massc.y/=mass;
  72. if(area<B2_FLT_EPSILON)
  73. continue;
  74. //Buoyancy
  75. b2Vec2 buoyancyForce = -density*area*gravity;
  76. body->ApplyForce(buoyancyForce,massc);
  77. //Linear drag
  78. b2Vec2 dragForce = body->GetLinearVelocityFromWorldPoint(areac) - velocity;
  79. dragForce *= -linearDrag*area;
  80. body->ApplyForce(dragForce,areac);
  81. //Angular drag
  82. //TODO: Something that makes more physical sense?
  83. body->ApplyTorque(-body->GetInertia()/body->GetMass()*area*body->GetAngularVelocity()*angularDrag);
  84. }
  85. }
  86. void b2BuoyancyController::Draw(b2DebugDraw *debugDraw)
  87. {
  88. float32 r = 1000;
  89. b2Vec2 p1 = offset * normal + b2Cross(normal, r);
  90. b2Vec2 p2 = offset * normal - b2Cross(normal, r);
  91. b2Color color(0,0,0.8f);
  92. debugDraw->DrawSegment(p1, p2, color);
  93. }
  94. void b2BuoyancyController::Destroy(b2BlockAllocator* allocator)
  95. {
  96. allocator->Free(this, sizeof(b2BuoyancyController));
  97. }
  98. b2BuoyancyController* b2BuoyancyControllerDef::Create(b2BlockAllocator* allocator)
  99. {
  100. void* mem = allocator->Allocate(sizeof(b2BuoyancyController));
  101. return new (mem) b2BuoyancyController(this);
  102. }