#ifndef PHISICS_H
#define PHISICS_H
#include "common.h"
typedef struct PhLink PhLink;
typedef struct PhNode PhNode;
typedef struct PhGroup PhGroup;
typedef struct Physics Physics;
typedef PhLink *PhCell;
struct PhLink {
PhNode *node;
PhCell *cell;
PhLink *prev, *next;
};
struct PhNode {
PhGroup *group;
PhNode *prev, *next;
PhLink l[4];
double r;
Vec p, gp, gk;
size_t mark; // temporary mark
PhNode *chain; // temporary chain
};
struct PhGroup {
Physics *ph;
PhGroup *prev, *next;
PhNode *first, *last;
int cnt;
Vec go, o, dx;
};
struct Physics {
PhGroup *first, *last;
double cs;
int hw, hh;
PhCell *cells;
size_t lastMark;
Vec b0, b1;
int fixangle;
};
void phLinkUnreg(PhLink *l);
void phLinkReg(PhLink *l, PhCell *c);
void phNodeUnregCell(PhNode *n);
void phNodeRegCell(PhNode *n, PhCell *c, int stride);
void phNodeUpdateCell(PhNode *n);
void phNodeUnreg(PhNode *n);
void phNodeReg(PhNode *n, PhGroup *g);
int phNodeBound(PhNode *n, Vec b0, Vec b1);
int phNodeCollision(PhNode *n);
static inline Vec phGroupTrans(PhGroup *g, Vec gp) { return vtrans(vsub(gp, g->go), g->dx, g->o); }
static inline Vec phGroupUntrans(PhGroup *g, Vec p) { return vadd(vuntrans(p, g->dx, g->o), g->go); }
void phGroupUpdateCells(PhGroup *g);
void phGroupUnreg(PhGroup *g);
void phGroupReg(PhGroup *g, Physics *ph);
void phGroupRecalc(PhGroup *g);
void phGroupPlaceNodes(PhGroup *g);
void phGroupFix(PhGroup *g, int fixangle);
void phGroupMove(PhGroup *g, Vec gp, Vec p, int fixangle);
void phGroupMerge(PhGroup *a, PhGroup *b);
void physicsAlloc(Physics *ph, int hw, int hh, double cs);
void physicsFree(Physics *ph);
PhCell* physicsCell(Physics *ph, Vec p);
void physicsClear(Physics *ph);
int physicsUpdate(Physics *ph);
void physicsDrawDebug(Physics *ph);
#endif