forked from Mirrors/openclonk
190 lines
6.1 KiB
C++
190 lines
6.1 KiB
C++
/*
|
|
* OpenClonk, http://www.openclonk.org
|
|
*
|
|
* Copyright (c) 2012 Armin Burgmeier
|
|
*
|
|
* Portions might be copyrighted by other authors who have contributed
|
|
* to OpenClonk.
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
* See isc_license.txt for full license and disclaimer.
|
|
*
|
|
* "Clonk" is a registered trademark of Matthes Bender.
|
|
* See clonk_trademark_license.txt for full license.
|
|
*/
|
|
|
|
#ifndef INC_C4Rope
|
|
#define INC_C4Rope
|
|
|
|
#include <stdexcept>
|
|
#include <C4Object.h>
|
|
|
|
// All units in pixels and frames
|
|
|
|
class C4RopeError: public std::runtime_error
|
|
{
|
|
public:
|
|
C4RopeError(const std::string& message): std::runtime_error(message) {}
|
|
};
|
|
|
|
// C4RopeLinks are intermediate rope elements that are inserted and removed
|
|
// such that
|
|
class C4RopeLink
|
|
{
|
|
public:
|
|
C4Real x, y; // pos
|
|
C4RopeLink* Next;
|
|
C4RopeLink* Prev;
|
|
};
|
|
|
|
class C4Rope;
|
|
class C4RopeElement
|
|
{
|
|
friend class C4Rope;
|
|
public:
|
|
C4RopeElement(C4Object* obj, bool fixed);
|
|
C4RopeElement(C4Real x, C4Real y, C4Real m, bool fixed);
|
|
~C4RopeElement();
|
|
|
|
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;
|
|
|
|
C4Real GetPrevLinkX() const { assert(Prev); return LastLink ? LastLink->x : Prev->oldx; }
|
|
C4Real GetPrevLinkY() const { assert(Prev); return LastLink ? LastLink->y : Prev->oldy; }
|
|
C4Real GetNextLinkX() const { assert(Next); return FirstLink ? FirstLink->x : Next->oldx; }
|
|
C4Real GetNextLinkY() const { assert(Next); return FirstLink ? FirstLink->y : Next->oldy; }
|
|
|
|
void AddForce(C4Real x, C4Real y);
|
|
void Execute(const C4Rope* rope, C4Real dt);
|
|
private:
|
|
bool InsertLinkPosition(int from_x, int from_y, int to_x, int to_y, int link_x, int link_y, int& insert_x, int& insert_y);
|
|
void InsertLink(C4RopeElement* from, C4RopeElement* to, int insert_x, int insert_y);
|
|
|
|
void ResetForceRedirection(C4Real dt);
|
|
void SetForceRedirection(const C4Rope* rope, int ox, int oy);
|
|
bool SetForceRedirectionByLookAround(const C4Rope* rope, int ox, int oy, C4Real dx, C4Real dy, C4Real l, C4Real angle);
|
|
|
|
bool Fixed; // Apply rope forces to this element?
|
|
C4Real x, y; // pos; ignored if Object != NULL
|
|
C4Real oldx, oldy; // position in the previous frame. Used for linking
|
|
C4Real vx, vy; // velocity; ignored if Object != NULL
|
|
C4Real m; // mass; ignored if Object != NULL
|
|
C4Real fx, fy; // force
|
|
C4Real rx, ry; // force redirection
|
|
C4Real rdt; // force redirection timeout
|
|
C4Real fcx, fcy; // force after solve -- for debug output only
|
|
C4RopeElement* Next; // next rope element, or NULL
|
|
C4RopeElement* Prev; // prev rope element, or NULL
|
|
C4RopeLink* FirstLink; // first rope link between this and next, or NULL
|
|
C4RopeLink* LastLink; // last rope link between this and prev, 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
|
|
{
|
|
public:
|
|
C4Rope(C4PropList* Prototype, C4Object* first_obj, C4Object* second_obj, C4Real segment_length, C4DefGraphics* graphics);
|
|
~C4Rope();
|
|
|
|
void Draw(C4TargetFacet& cgo, C4BltTransform* pTransform);
|
|
void Execute();
|
|
|
|
void ClearPointers(C4Object* obj);
|
|
|
|
C4Real GetSegmentLength() const { return l; }
|
|
C4Real GetOuterFriction() const { return mu; }
|
|
|
|
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; 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; }
|
|
void SetFrontAutoSegmentation(C4Real max) { FrontAutoSegmentation = max; }
|
|
void SetBackAutoSegmentation(C4Real max) { BackAutoSegmentation = max; }
|
|
|
|
bool GetFrontFixed() const { return Front->Fixed; }
|
|
bool GetBackFixed() const { return Back->Fixed; }
|
|
void SetFrontFixed(bool fixed) { Front->Fixed = fixed; }
|
|
void SetBackFixed(bool fixed) { Back->Fixed = fixed; }
|
|
|
|
void PullFront(C4Real f) { FrontPull = f; }
|
|
void PullBack(C4Real f) { BackPull = f; }
|
|
private:
|
|
C4Real GetL(const C4RopeElement* prev, const C4RopeElement* next) const;
|
|
|
|
void DoAutoSegmentation(C4RopeElement* fixed, C4RopeElement* first, C4Real max);
|
|
void Solve(C4RopeElement* prev, C4RopeElement* next);
|
|
|
|
// Whether to apply repulsive forces between rope segments.
|
|
// TODO: Could be made a property...
|
|
static const bool ApplyRepulsive = false;
|
|
|
|
unsigned int NumIterations; // Number of iterations per frame
|
|
const float Width; // Width of rope
|
|
C4DefGraphics* Graphics;
|
|
int32_t SegmentCount;
|
|
|
|
C4Real l; // spring length in equilibrium
|
|
C4Real k; // spring constant
|
|
C4Real mu; // outer friction constant
|
|
C4Real eta; // inner friction constant
|
|
|
|
C4RopeElement* Front;
|
|
C4RopeElement* Back;
|
|
|
|
C4Real FrontAutoSegmentation;
|
|
C4Real BackAutoSegmentation;
|
|
|
|
C4Real FrontPull;
|
|
C4Real BackPull;
|
|
};
|
|
|
|
class C4RopeAul: public C4AulScript
|
|
{
|
|
public:
|
|
C4RopeAul();
|
|
virtual ~C4RopeAul();
|
|
|
|
virtual bool Delete() { return false; }
|
|
virtual C4PropListStatic* GetPropList() { return RopeDef; }
|
|
|
|
void InitFunctionMap(C4AulScriptEngine* pEngine);
|
|
|
|
protected:
|
|
C4PropListStatic* RopeDef;
|
|
};
|
|
|
|
class C4RopeList
|
|
{
|
|
public:
|
|
C4RopeList();
|
|
|
|
void InitFunctionMap(C4AulScriptEngine* pEngine) { RopeAul.InitFunctionMap(pEngine); }
|
|
|
|
void Execute();
|
|
void Draw(C4TargetFacet& cgo, C4BltTransform* pTransform);
|
|
|
|
C4Rope* CreateRope(C4Object* first_obj, C4Object* second_obj, C4Real segment_length, C4DefGraphics* graphics);
|
|
void RemoveRope(C4Rope* rope);
|
|
|
|
void ClearPointers(C4Object* obj);
|
|
|
|
private:
|
|
C4RopeAul RopeAul;
|
|
std::vector<C4Rope*> Ropes;
|
|
};
|
|
|
|
#endif // INC_C4Rope
|