Blame projects/jigsaw/phisics.node.c

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