void pl_collcontext_insert_object(pl_collisioncontext_t *ctxt, pl_recgrid_t *grid, pl_object_t *obj) { int octant = getoctant(&grid->centre, obj); if (grid->children[octant] && fits(grid->children[octant], obj)){ pl_collcontext_insert_object(ctxt, grid->children[octant], obj); } else { obj_array_push(&grid->objs, obj); } if (grid->objs.length > THRESHOLD) { split(ctxt, grid); } }
void plInsertObject(PLcollisioncontext *ctxt, PLrecgrid *grid, PLobject *obj) { int octant = getoctant(&grid->centre, obj); if (grid->children[octant] && fits(grid->children[octant], obj)){ plInsertObject(ctxt, grid->children[octant], obj); } else { obj_array_push(&grid->objs, obj); } if (grid->objs.length > THRESHOLD) { split(ctxt, grid); } }
static void split(pl_collisioncontext_t *ctxt, pl_recgrid_t *grid) { if (grid->children[0] == NULL) { for (int i = 0 ; i < 8 ; i++) { grid->children[i] = pl_new_recgrid(ctxt, grid->size/2.0); grid->children[i]->centre = grid->centre; } lwc_translate3f(&grid->children[0]->centre, grid->size/4.0, grid->size/4.0, grid->size/4.0); lwc_translate3f(&grid->children[1]->centre, grid->size/4.0, grid->size/4.0, -grid->size/4.0); lwc_translate3f(&grid->children[2]->centre, grid->size/4.0, -grid->size/4.0, grid->size/4.0); lwc_translate3f(&grid->children[3]->centre, grid->size/4.0, -grid->size/4.0, -grid->size/4.0); lwc_translate3f(&grid->children[4]->centre, -grid->size/4.0, grid->size/4.0, grid->size/4.0); lwc_translate3f(&grid->children[5]->centre, -grid->size/4.0, grid->size/4.0, -grid->size/4.0); lwc_translate3f(&grid->children[6]->centre, -grid->size/4.0, -grid->size/4.0, grid->size/4.0); lwc_translate3f(&grid->children[7]->centre, -grid->size/4.0, -grid->size/4.0, -grid->size/4.0); } for (int i = 0 ; i < grid->objs.length ; i++) { pl_object_t *obj = grid->objs.elems[i]; int octant = getoctant(&grid->centre, obj); if (fits(grid->children[octant], obj)) { pl_collcontext_insert_object(ctxt, grid->children[octant], obj); obj_array_remove(&grid->objs, i); i --; } } }
static void split(PLcollisioncontext *ctxt, PLrecgrid *grid) { if (grid->children[0] == NULL) { for (int i = 0 ; i < 8 ; i++) { grid->children[i] = plNewRecgrid(ctxt, grid->size/2.0); grid->children[i]->centre = grid->centre; } ooLwcTranslate3f(&grid->children[0]->centre, grid->size/4.0, grid->size/4.0, grid->size/4.0); ooLwcTranslate3f(&grid->children[1]->centre, grid->size/4.0, grid->size/4.0, -grid->size/4.0); ooLwcTranslate3f(&grid->children[2]->centre, grid->size/4.0, -grid->size/4.0, grid->size/4.0); ooLwcTranslate3f(&grid->children[3]->centre, grid->size/4.0, -grid->size/4.0, -grid->size/4.0); ooLwcTranslate3f(&grid->children[4]->centre, -grid->size/4.0, grid->size/4.0, grid->size/4.0); ooLwcTranslate3f(&grid->children[5]->centre, -grid->size/4.0, grid->size/4.0, -grid->size/4.0); ooLwcTranslate3f(&grid->children[6]->centre, -grid->size/4.0, -grid->size/4.0, grid->size/4.0); ooLwcTranslate3f(&grid->children[7]->centre, -grid->size/4.0, -grid->size/4.0, -grid->size/4.0); } for (int i = 0 ; i < grid->objs.length ; i++) { PLobject *obj = grid->objs.elems[i]; int octant = getoctant(&grid->centre, obj); if (fits(grid->children[octant], obj)) { plInsertObject(ctxt, grid->children[octant], obj); obj_array_remove(&grid->objs, i); i --; } } }
/* ================================================= */ void lconiclist(ellipse *ell, int32_t rs, int32_t cs, int32_t xs, int32_t ys, int32_t xe, int32_t ye, int32_t A, int32_t B, int32_t C, int32_t D, int32_t E, int32_t F, int32_t xoffset, int32_t yoffset) /* ================================================= */ { int32_t octant; int32_t dxS, dyS, dxD, dyD; int32_t d,u,v; int32_t k1sign, k1, Bsign, k2, k3; int32_t gxe, gye, gx, gy; int32_t octantcount; int32_t x, y; int32_t tmp, tmpdk; A *= 4; B *= 4; C *= 4; D *= 4; E *= 4; F *= 4; if (DEBUG) fprintf(stderr,"lconic -- %d %d %d %d %d %d\n", xs, ys, xe, ye, xoffset, yoffset); if (DEBUG) fprintf(stderr,"lconic -- %d %d %d %d %d %d\n", A,B,C,D,E,F); /* Translate start point to origin... */ /* F = A*xs*xs + B*xs*ys + C*ys*ys + D*xs + E*ys + F; D = D + 2 * A * xs + B * ys; E = E + B * xs + 2 * C * ys; */ /* Work out starting octant */ octant = getoctant(D,E); dxS = SIDEx[octant]; dyS = SIDEy[octant]; dxD = DIAGx[octant]; dyD = DIAGy[octant]; switch (octant) { case 1: d = A + B/2 + C/4 + D + E/2 + F; u = A + B/2 + D; v = u + E; break; case 2: d = A/4 + B/2 + C + D/2 + E + F; u = B/2 + C + E; v = u + D; break; case 3: d = A/4 - B/2 + C - D/2 + E + F; u = -B/2 + C + E; v = u - D; break; case 4: d = A - B/2 + C/4 - D + E/2 + F; u = A - B/2 - D; v = u + E; break; case 5: d = A + B/2 + C/4 - D - E/2 + F; u = A + B/2 - D; v = u - E; break; case 6: d = A/4 + B/2 + C - D/2 - E + F; u = B/2 + C - E; v = u - D; break; case 7: d = A/4 - B/2 + C + D/2 - E + F; u = -B/2 + C - E; v = u + D; break; case 8: d = A - B/2 + C/4 + D - E/2 + F; u = A - B/2 + D; v = u - E; break; default: fprintf(stderr,"FUNNY OCTANT\n"); abort(); } k1sign = dyS*dyD; k1 = 2 * (A + k1sign * (C - A)); Bsign = dxD*dyD; k2 = k1 + Bsign * B; k3 = 2 * (A + C + Bsign * B); /* Work out gradient at endpoint */ gxe = xe - xs; gye = ye - ys; gx = 2*A*gxe + B*gye + D; gy = B*gxe + 2*C*gye + E; octantcount = getoctant(gx,gy) - octant; if (octantcount < 0) octantcount = octantcount + 8; else if (octantcount==0) if((xs>xe && dxD>0) || (ys>ye && dyD>0) || (xs<xe && dxD<0) || (ys<ye && dyD<0)) octantcount +=8; if (DEBUG) fprintf(stderr,"octantcount = %d\n", octantcount); x = xs; y = ys; while (octantcount > 0) { if (DEBUG) fprintf(stderr,"-- %d -------------------------\n", octant); if (mcodd(octant)) { while (2*v <= k2) { /* Plot this point */ plotlist(ell, rs, cs, x+xoffset, y+yoffset); /* Are we inside or outside? */ if (DEBUG) fprintf(stderr,"x = %3d y = %3d d = %4d\n", x,y,d); if (d < 0) { /* Inside */ x = x + dxS; y = y + dyS; u = u + k1; v = v + k2; d = d + u; } else { /* outside */ x = x + dxD; y = y + dyD; u = u + k2; v = v + k3; d = d + v; } } d = d - u + v/2 - k2/2 + 3*k3/8; /* error (^) in Foley and van Dam p 959, "2nd ed, revised 5th printing" */ u = -u + v - k2/2 + k3/2; v = v - k2 + k3/2; k1 = k1 - 2*k2 + k3; k2 = k3 - k2; tmp = dxS; dxS = -dyS; dyS = tmp; } else { /* Octant is even */ while (2*u < k2) { /* Plot this point */ plotlist(ell, rs, cs, x+xoffset, y+yoffset); if (DEBUG) fprintf(stderr,"x = %3d y = %3d d = %4d\n", x,y,d); /* Are we inside or outside? */ if (d > 0) { /* Outside */ x = x + dxS; y = y + dyS; u = u + k1; v = v + k2; d = d + u; } else { /* Inside */ x = x + dxD; y = y + dyD; u = u + k2; v = v + k3; d = d + v; } } tmpdk = k1 - k2; d = d + u - v + tmpdk; v = 2*u - v + tmpdk; u = u + tmpdk; k3 = k3 + 4*tmpdk; k2 = k1 + tmpdk; tmp = dxD; dxD = -dyD; dyD = tmp; } octant = (octant&7)+1; octantcount--; } /* Draw final octant until we reach the endpoint */ if (DEBUG) fprintf(stderr,"-- %d (final) -----------------\n", octant); if (mcodd(octant)) { while (2*v <= k2) { /* Plot this point */ plotlist(ell, rs, cs, x+xoffset, y+yoffset); if (x == xe && y == ye) break; if (DEBUG) fprintf(stderr,"x = %3d y = %3d d = %4d\n", x,y,d); /* Are we inside or outside? */ if (d < 0) { /* Inside */ x = x + dxS; y = y + dyS; u = u + k1; v = v + k2; d = d + u; } else { /* outside */ x = x + dxD; y = y + dyD; u = u + k2; v = v + k3; d = d + v; } } } else { /* Octant is even */ while ((2*u < k2)) { /* Plot this point */ plotlist(ell, rs, cs, x+xoffset, y+yoffset); if (x == xe && y == ye) break; if (DEBUG) fprintf(stderr,"x = %3d y = %3d d = %4d\n", x,y,d); /* Are we inside or outside? */ if (d > 0) { /* Outside */ x = x + dxS; y = y + dyS; u = u + k1; v = v + k2; d = d + u; } else { /* Inside */ x = x + dxD; y = y + dyD; u = u + k2; v = v + k3; d = d + v; } } } } /* lconiclist() */