|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
#include "phisics.h"
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
void phLinkUnreg(PhLink *l) {
|
|
Ivan Mahonin |
fdbd7d |
if (!l->cell) return;
|
|
Ivan Mahonin |
fdbd7d |
l->next->prev = l->prev; l->prev->next = l->next;
|
|
Ivan Mahonin |
fdbd7d |
if (l->next == l) *l->cell = NULL; else
|
|
Ivan Mahonin |
fdbd7d |
if (*l->cell == l) *l->cell = l->next;
|
|
Ivan Mahonin |
fdbd7d |
l->cell = NULL;
|
|
Ivan Mahonin |
fdbd7d |
l->prev = l->next = NULL;
|
|
Ivan Mahonin |
fdbd7d |
}
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
void phLinkReg(PhLink *l, PhCell *c) {
|
|
Ivan Mahonin |
fdbd7d |
if (l->cell == c) return;
|
|
Ivan Mahonin |
fdbd7d |
phLinkUnreg(l);
|
|
Ivan Mahonin |
fdbd7d |
if (*c) {
|
|
Ivan Mahonin |
fdbd7d |
l->next = *c;
|
|
Ivan Mahonin |
fdbd7d |
l->prev = l->next->prev;
|
|
Ivan Mahonin |
fdbd7d |
l->next->prev = l;
|
|
Ivan Mahonin |
fdbd7d |
l->prev->next = l;
|
|
Ivan Mahonin |
fdbd7d |
} else {
|
|
Ivan Mahonin |
fdbd7d |
*c = l;
|
|
Ivan Mahonin |
fdbd7d |
l->next = l->prev = l;
|
|
Ivan Mahonin |
fdbd7d |
}
|
|
Ivan Mahonin |
fdbd7d |
l->cell = c;
|
|
Ivan Mahonin |
fdbd7d |
}
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
void phNodeUnregCell(PhNode *n)
|
|
Ivan Mahonin |
fdbd7d |
{ for(int i = 0; i < 4; ++i) phLinkUnreg(n->l+i); }
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
void phNodeRegCell(PhNode *n, PhCell *c, int stride) {
|
|
Ivan Mahonin |
fdbd7d |
if (n->l->cell == c) return;
|
|
Ivan Mahonin |
fdbd7d |
phLinkReg(n->l+0, c);
|
|
Ivan Mahonin |
fdbd7d |
phLinkReg(n->l+1, c+1);
|
|
Ivan Mahonin |
fdbd7d |
phLinkReg(n->l+2, c+stride);
|
|
Ivan Mahonin |
fdbd7d |
phLinkReg(n->l+3, c+stride+1);
|
|
Ivan Mahonin |
fdbd7d |
}
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
void phNodeUpdateCell(PhNode *n) {
|
|
Ivan Mahonin |
fdbd7d |
if (n->group && n->group->ph)
|
|
Ivan Mahonin |
fdbd7d |
phNodeRegCell(n, physicsCell(n->group->ph, n->p), n->group->ph->hw*2);
|
|
Ivan Mahonin |
fdbd7d |
else
|
|
Ivan Mahonin |
fdbd7d |
phNodeUnregCell(n);
|
|
Ivan Mahonin |
fdbd7d |
}
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
void phNodeUnreg(PhNode *n) {
|
|
Ivan Mahonin |
fdbd7d |
if (!n->group) return;
|
|
Ivan Mahonin |
fdbd7d |
phNodeUnregCell(n);
|
|
Ivan Mahonin |
fdbd7d |
*(n->prev ? &n->prev->next : &n->group->first) = n->next;
|
|
Ivan Mahonin |
fdbd7d |
*(n->next ? &n->next->prev : &n->group->last) = n->prev;
|
|
Ivan Mahonin |
fdbd7d |
n->prev = n->next = NULL;
|
|
Ivan Mahonin |
fdbd7d |
n->group = NULL;
|
|
Ivan Mahonin |
fdbd7d |
}
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
void phNodeReg(PhNode *n, PhGroup *g) {
|
|
Ivan Mahonin |
fdbd7d |
if (n->group == g) return;
|
|
Ivan Mahonin |
fdbd7d |
phNodeUnreg(n);
|
|
Ivan Mahonin |
fdbd7d |
for(int i = 0; i < 4; ++i) n->l[i].node = n;
|
|
Ivan Mahonin |
fdbd7d |
n->group = g;
|
|
Ivan Mahonin |
fdbd7d |
n->prev = g->last;
|
|
Ivan Mahonin |
fdbd7d |
*(n->prev ? &n->prev->next : &g->first) = g->last = n;
|
|
Ivan Mahonin |
fdbd7d |
phNodeUpdateCell(n);
|
|
Ivan Mahonin |
fdbd7d |
}
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
int phNodeBound(PhNode *n, Vec b0, Vec b1) {
|
|
Ivan Mahonin |
fdbd7d |
double d;
|
|
Ivan Mahonin |
fdbd7d |
int res = 0;
|
|
Ivan Mahonin |
fdbd7d |
d = n->p.x - b0.x - n->r; if (d < 0) n->p.x -= d, res = 1;
|
|
Ivan Mahonin |
fdbd7d |
d = b1.x - n->p.x - n->r; if (d < 0) n->p.x += d, res = 1;
|
|
Ivan Mahonin |
fdbd7d |
d = n->p.y - b0.y - n->r; if (d < 0) n->p.y -= d, res = 1;
|
|
Ivan Mahonin |
fdbd7d |
d = b1.y - n->p.y - n->r; if (d < 0) n->p.y += d, res = 1;
|
|
Ivan Mahonin |
fdbd7d |
if (res) phNodeUpdateCell(n);
|
|
Ivan Mahonin |
fdbd7d |
return res;
|
|
Ivan Mahonin |
fdbd7d |
}
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
int phNodeCollision(PhNode *n) {
|
|
Ivan Mahonin |
fdbd7d |
if (!n->group || !n->group->ph) return 0;
|
|
Ivan Mahonin |
fdbd7d |
PhNode *chain = n;
|
|
Ivan Mahonin |
fdbd7d |
unsigned int mark = ++n->group->ph->lastMark;
|
|
Ivan Mahonin |
fdbd7d |
for(int i = 0; i < 4; ++i) {
|
|
Ivan Mahonin |
fdbd7d |
PhLink *link = n->l+i;
|
|
Ivan Mahonin |
fdbd7d |
for(PhLink *l = link->next; l && l != link; l = l->next) {
|
|
Ivan Mahonin |
fdbd7d |
PhNode *m = l->node;
|
|
Ivan Mahonin |
fdbd7d |
if (m >= n || m->mark == mark) continue;
|
|
Ivan Mahonin |
fdbd7d |
m->mark = mark;
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
if (n->group == m->group) continue;
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
double r = n->r + m->r;
|
|
Ivan Mahonin |
fdbd7d |
Vec d = vsub(m->p, n->p);
|
|
Ivan Mahonin |
fdbd7d |
double l2 = vlen2(d);
|
|
Ivan Mahonin |
fdbd7d |
if (!(l2 < r*r)) continue;
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
double l = sqrt(l2);
|
|
Ivan Mahonin |
fdbd7d |
d = vmul(d, (r*1.001 - l)/l/2);
|
|
Ivan Mahonin |
fdbd7d |
n->p = vsub(n->p, d);
|
|
Ivan Mahonin |
fdbd7d |
m->p = vadd(m->p, d);
|
|
Ivan Mahonin |
fdbd7d |
m->chain = chain;
|
|
Ivan Mahonin |
fdbd7d |
chain = m;
|
|
Ivan Mahonin |
fdbd7d |
}
|
|
Ivan Mahonin |
fdbd7d |
}
|
|
Ivan Mahonin |
fdbd7d |
if (chain == n) return 0;
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
int res = 0;
|
|
Ivan Mahonin |
fdbd7d |
while(chain) {
|
|
Ivan Mahonin |
fdbd7d |
phNodeUpdateCell(chain);
|
|
Ivan Mahonin |
fdbd7d |
PhNode *nn = chain->chain;
|
|
Ivan Mahonin |
fdbd7d |
chain->chain = NULL;
|
|
Ivan Mahonin |
fdbd7d |
chain = nn;
|
|
Ivan Mahonin |
fdbd7d |
++res;
|
|
Ivan Mahonin |
fdbd7d |
}
|
|
Ivan Mahonin |
fdbd7d |
return res;
|
|
Ivan Mahonin |
fdbd7d |
}
|
|
Ivan Mahonin |
fdbd7d |
|
|
Ivan Mahonin |
fdbd7d |
|