Rope: Compute forces from last contact vertex for connected objects

rope
Armin Burgmeier 2012-05-06 19:14:25 +02:00
parent 2aef0d896d
commit 6006b83aa6
2 changed files with 37 additions and 9 deletions

View File

@ -150,14 +150,14 @@ namespace
C4RopeElement::C4RopeElement(C4Object* obj, bool fixed):
Fixed(fixed), fx(Fix0), fy(Fix0), rx(Fix0), ry(Fix0), rdt(Fix0), fcx(Fix0), fcy(Fix0),
Next(NULL), Prev(NULL), Object(obj)
Next(NULL), Prev(NULL), Object(obj), LastContactVertex(-1)
{
}
C4RopeElement::C4RopeElement(C4Real x, C4Real y, C4Real m, bool fixed):
Fixed(fixed), x(x), y(y), vx(Fix0), vy(Fix0), m(m),
fx(Fix0), fy(Fix0), rx(Fix0), ry(Fix0), rdt(Fix0), fcx(Fix0), fcy(Fix0),
Next(NULL), Prev(NULL), Object(NULL)
Next(NULL), Prev(NULL), Object(NULL), LastContactVertex(-1)
{
}
@ -172,6 +172,30 @@ void C4RopeElement::AddForce(C4Real x, C4Real y)
#endif
}
C4Real C4RopeElement::GetTargetX() const
{
// TODO: Prevent against object changes: Reset when Target changes wrt
// to the object LastContactVertex refers to.
if(LastContactVertex == -1) return Object->fix_x;
C4Object* obj = Object;
while(obj->Contained)
obj = obj->Contained;
return obj->fix_x + itofix(obj->Shape.VtxX[LastContactVertex]);
}
C4Real C4RopeElement::GetTargetY() const
{
// TODO: Prevent against object changes: Reset when Target changes wrt
// to the object LastContactVertex refers to.
if(LastContactVertex == -1) return Object->fix_y;
C4Object* obj = Object;
while(obj->Contained)
obj = obj->Contained;
return obj->fix_y + itofix(obj->Shape.VtxY[LastContactVertex]);
}
void C4RopeElement::Execute(const C4Rope* rope, C4Real dt)
{
ResetForceRedirection(dt);
@ -279,7 +303,10 @@ void C4RopeElement::Execute(const C4Rope* rope, C4Real dt)
iContactVertex = i;
if(iContactVertex != -1)
{
LastContactVertex = iContactVertex;
SetForceRedirection(rope, Target->Shape.VtxX[iContactVertex], Target->Shape.VtxY[iContactVertex]);
}
}
}
}
@ -520,9 +547,6 @@ void C4Rope::Solve(C4RopeElement* prev, C4RopeElement* next)
int nix = fixtoi(next->GetX());
int niy = fixtoi(next->GetY());
// TODO: For objects, run PathFree and PathFinder from vertex which has
// had contact to the landscape previously.
// We only run the PathFinder when the distance between the two segments
// is at least twice the nominal distance.

View File

@ -37,13 +37,16 @@ public:
C4RopeElement(C4Object* obj, bool fixed);
C4RopeElement(C4Real x, C4Real y, C4Real m, bool fixed);
C4Real GetX() const { return Object ? Object->fix_x : x; }
C4Real GetY() const { return Object ? Object->fix_y : y; }
C4Real GetX() const { return Object ? GetTargetX() : x; }
C4Real GetY() const { return Object ? GetTargetY() : y; }
C4Real GetVx() const { return Object ? Object->xdir : vx; }
C4Real GetVy() const { return Object ? Object->ydir : vy; }
C4Real GetMass() const { return Object ? itofix(Object->Mass) : m; }
C4Object* GetObject() const { return Object; }
C4Real GetTargetX() const;
C4Real GetTargetY() const;
void AddForce(C4Real x, C4Real y);
void Execute(const C4Rope* rope, C4Real dt);
private:
@ -62,6 +65,7 @@ private:
C4RopeElement* Next; // next rope element, or NULL
C4RopeElement* Prev; // prev rope element, or NULL
C4Object* Object; // Connected object. If set, x/y/vx/vy/m are ignored.
int LastContactVertex; // Vertex which most recently had collision with landscape
};
class C4Rope: public C4PropListNumbered
@ -80,8 +84,8 @@ public:
C4RopeElement* GetFront() const { return Front; }
C4RopeElement* GetBack() const { return Back; }
void SetFront(C4Object* obj, C4Real x, C4Real y) { Front->Object = obj; Front->x = x; Front->y = y; }
void SetBack(C4Object* obj, C4Real x, C4Real y) { Back->Object = obj; Back->x = x; Back->y = y; }
void SetFront(C4Object* obj, C4Real x, C4Real y) { Front->Object = obj; Front->x = x; Front->y = y; Front->LastContactVertex = -1; }
void SetBack(C4Object* obj, C4Real x, C4Real y) { Back->Object = obj; Back->x = x; Back->y = y; Back->LastContactVertex = -1; }
C4Real GetFrontAutoSegmentation() const { return FrontAutoSegmentation; }
C4Real GetBackAutoSegmentation() const { return BackAutoSegmentation; }