Beispiel #1
0
local void sumforces(bodyptr btab, int nbody, bodyptr gtab, int ngrav,
		     real eps2)
{
  bodyptr bp, gp;
  double phi0, acc0[NDIM];
  vector pos0, dr;
  real dr2, dr2i, dr1i, mdr1i, mdr3i;

  for (bp = btab; bp < NthBody(btab, nbody); bp = NextBody(bp)) {
    phi0 = 0.0;
    CLRV(acc0);
    SETV(pos0, Pos(bp));
    for (gp = gtab; gp < NthBody(gtab, ngrav); gp = NextBody(gp)) {
      DOTPSUBV(dr2, dr, Pos(gp), pos0);
      dr2i = ((real) 1.0) / (dr2 + eps2);
      dr1i = rsqrt(dr2i);
      mdr1i = Mass(gp) * dr1i;
      mdr3i = mdr1i * dr2i;
      phi0 -= mdr1i;
      ADDMULVS(acc0, dr, mdr3i);
    }
    Phi(bp) = phi0;
    SETV(Acc(bp), acc0);
  }
}
Beispiel #2
0
void calculateCenterOfMass(cellptr cell)
{
	/* Center of mass position */
	vector cmPos;
	vector tempV;
	nodeptr q;
	int i;
	/* Init the cell's total mass */
	Mass(cell) = 0.0;
	/* Init the cell's center of mass position */
	CLRV(cmPos);
	/* Loop over the subnodes */
	for (i = 0; i < NCHILD; i++) {
		/* Skipping empty child nodes */
		if ((q = Child(cell)[i]) != NULL) {
			/* If node is a cell */
			if (Type(q) == CELL)
				/* Recursively do the same */
				calculateCenterOfMass((cellptr) q);
			/* Accumulate total mass */
			Mass(cell) = Mass(q);
			/* Accumulate center of mass */
			ADDMULVS(cmPos, Pos(q), Mass(q));
		}
	}
	/* Usually, cell has mass */
	if (Mass(cell) > 0.0) {
		/* Find center of mass position */
		DIVVS(cmPos, cmPos, Mass(cell));
	} else { /* If no mass inside */
		SETV(cmPos, Pos(cell));
	}
	SETV(Pos(cell), cmPos);
}
Beispiel #3
0
local void sum1force(bodyptr btab, int nbody, int i0, real eps2)
{
    bodyptr bp0, bp;
    double phi0, acc0[NDIM];
    vector pos0, dr;
    real dr2, drab, mri, mr3i;
    int j;

    bp0 = NthBody(btab, i0);
    phi0 = 0.0;
    CLRV(acc0);
    SETV(pos0, Pos(bp0));
    for (j = 0; j < nbody; j++)
	if (j != i0) {
	    bp = NthBody(btab, j);
	    DOTPSUBV(dr2, dr, Pos(bp), pos0);
	    dr2 += eps2;
	    drab = rsqrt(dr2);
	    mri = Mass(bp) / drab;
	    phi0 -= mri;
	    mr3i = mri / dr2;
	    ADDMULVS(acc0, dr, mr3i);
	}
    Phi(bp0) = phi0;
    SETV(Acc(bp0), acc0);
}
Beispiel #4
0
EXTERN_ENV
#define global extern

#include "stdinc.h"

/*
 * HACKGRAV: evaluate grav field at a given particle.
 */

void hackgrav(bodyptr p, long ProcessId)
{
   Local[ProcessId].pskip = p;
   SETV(Local[ProcessId].pos0, Pos(p));
   Local[ProcessId].phi0 = 0.0;
   CLRV(Local[ProcessId].acc0);
   Local[ProcessId].myn2bterm = 0;
   Local[ProcessId].mynbcterm = 0;
   Local[ProcessId].skipself = FALSE;
   hackwalk(ProcessId);
   Phi(p) = Local[ProcessId].phi0;
   SETV(Acc(p), Local[ProcessId].acc0);
#ifdef QUADPOLE
   Cost(p) = Local[ProcessId].myn2bterm + NDIM * Local[ProcessId].mynbcterm;
#else
   Cost(p) = Local[ProcessId].myn2bterm + Local[ProcessId].mynbcterm;
#endif
}
Beispiel #5
0
int read_snapshot(
		   bodyptr *btab_ptr,	     /* gets particle array */
		   int *nobj_ptr,	     /* gets number of bodies */
		   stream instr              /* stream to read from */
		   )
{
  int nobj, cs, i;
  real *mbuf, *mp, *pbuf, *pp;
  bodyptr bp;

  for(;;) {                        /* loop until done or proper snapshot */
    if (!get_tag_ok(instr,SnapShotTag))
        return 0;
    get_set(instr, SnapShotTag);
    if (!get_tag_ok(instr,ParametersTag)) {
    	get_tes(instr,SnapShotTag);
        continue;
    }
    get_set(instr, ParametersTag);
    get_data(instr, NobjTag, IntType, &nobj, 0);
    if (nobj < 1)
	error("read_snapshot: %s = %d  is absurd", NobjTag, nobj);
    if (get_tag_ok(instr,TimeTag))
        get_data(instr,TimeTag, RealType, &tsnap, 0);
    else {
        dprintf(0,"No time tag: time=0.0 assumed\n");
        tsnap = 0.0;
    }
    get_tes(instr, ParametersTag);
    if (!get_tag_ok(instr,ParticlesTag)) {
    	get_tes(instr,SnapShotTag);
        continue;
    }
    get_set(instr, ParticlesTag);
    get_data(instr, CoordSystemTag, IntType, &cs, 0);
    if (cs != CSCode(Cartesian, NDIM, 2))
	error("read_snapshot: cannot handle %s = %d", CoordSystemTag, cs);
    mbuf = mp = (real *) allocate(nobj * sizeof(real));
    pbuf = pp = (real *) allocate(nobj * 2 * NDIM * sizeof(real));
    get_data(instr, MassTag, RealType, mbuf, nobj, 0);
    get_data(instr, PhaseSpaceTag, RealType, pbuf, nobj, 2, NDIM, 0);
    get_tes(instr, ParticlesTag);
    get_tes(instr, SnapShotTag);
    *btab_ptr = bp = (bodyptr) allocate(nobj * sizeof(body));
    for (i = 0; i < nobj; i++) {
	Type(bp) = BODY;
	Mass(bp) = *mp++;
	SETV(Pos(bp), pp);
	pp += NDIM;
	SETV(Vel(bp), pp);
	pp += NDIM;
	bp++;
    }
    free(mbuf);
    free(pbuf);
    *nobj_ptr = nobj;
    return 1;
  }
}
Beispiel #6
0
local void walktree(nodeptr *aptr, nodeptr *nptr, cellptr cptr, cellptr bptr,
                    nodeptr p, real psize, vector pmid)
{
  nodeptr *np, *ap, q;
  int actsafe;
  matrix trQM;
 
  if (Update(p)) {				// new forces needed in node?
    np = nptr;					// start new active list
    actsafe = actmax - NSUB;			// leave room for NSUB more
    for (ap = aptr; ap < nptr; ap++) {		// loop over active nodes
      if (Type(*ap) == CELL) {			// is this node a cell?
	if (accept(*ap, psize, pmid)) {		// does it pass the test?
	  if (Mass(*ap) > 0.0) {		// and contribute to field?
	    Mass(cptr) = Mass(*ap);		// copy to interaction list
	    SETV(Pos(cptr), Pos(*ap));
#if defined(SOFTCORR)
	    TRACEM(Trace(cptr), Quad(*ap));	// save trace in copy
	    SETMI(trQM);
	    MULMS(trQM, trQM, Trace(cptr)/3);
	    SUBM(Quad(cptr), Quad(*ap), trQM);	// store traceless moment
#else
	    SETM(Quad(cptr), Quad(*ap));	// copy traceless moment
#endif
	    cptr++;				// and bump cell array ptr
	  }
	} else {				// this cell fails the test
	  if (np - active >= actsafe)		// make sure list has room
	    fatal("%s.walktree: active list overflow\n", getprog());
	  for (q = More(*ap); q != Next(*ap); q = Next(q))
						// loop over all subcells
	    *np++= q;				// put them on active list
	}
      } else					// else this node is a body
	if (*ap != p && Mass(*ap) > 0.0) {	// not self-interaction?
	  --bptr;				// bump body array ptr
	  Mass(bptr) = Mass(*ap);		// and copy data to array
	  SETV(Pos(bptr), Pos(*ap));
	}
    }
    acttot = MAX(acttot, np - active);		// keep track of max active
    if (np != nptr) {				// if new actives were added
      walksub(nptr, np, cptr, bptr, p, psize, pmid);
						// then visit next level
    } else {					// else no actives left
      if (Type(p) != BODY)			// make sure we got a body
	fatal("%s.walktree: recursion terminated with cell\n"
	      "  p = 0x%x  psize   = %.8f  Mass(p) = %g\n"
	      "  pmid =   (%.8f,%.8f,%.8f)\n  Pos(p) = (%.8f,%.8f,%.8f)\n",
	      getprog(), (int) p, psize, Mass(p),
	      pmid[0], pmid[1], pmid[2], Pos(p)[0], Pos(p)[1], Pos(p)[2]);
      gravsum((bodyptr) p, cptr, bptr);		// sum force on this body
    }
  }
}
Beispiel #7
0
void snaprect(bodyptr btab, int nbody)
{
  matrix qmat, tmpm;
  bodyptr bp;
  vector frame[3], tmpv;
  static vector oldframe[3] =
    { { 1.0, 0.0, 0.0, }, { 0.0, 1.0, 0.0, }, { 0.0, 0.0, 1.0, }, };
  int i;

  snapcenter(btab, nbody, WeightField.offset);
  CLRM(qmat);
  for (bp = btab; bp < NthBody(btab, nbody); bp = NextBody(bp)) {
    OUTVP(tmpm, Pos(bp), Pos(bp));
    MULMS(tmpm, tmpm, Weight(bp));
    ADDM(qmat, qmat, tmpm);
  }
  eigenvect(frame[0], frame[1], frame[2], qmat);
  if (dotvp(oldframe[0], frame[0]) < 0.0)
    MULVS(frame[0], frame[0], -1.0);
  if (dotvp(oldframe[2], frame[2]) < 0.0)
    MULVS(frame[2], frame[2], -1.0);
  CROSSVP(frame[1], frame[2], frame[0]);
  printvect("e_x:", frame[0]);
  printvect("e_y:", frame[1]);
  printvect("e_z:", frame[2]);
  for (bp = btab; bp < NthBody(btab, nbody); bp = NextBody(bp)) {
    if (PosField.offset != BadOffset) {
      for (i = 0; i < NDIM; i++)
	tmpv[i] = dotvp(Pos(bp), frame[i]);
      SETV(Pos(bp), tmpv);
    }
    if (VelField.offset != BadOffset) {
      for (i = 0; i < NDIM; i++)
	tmpv[i] = dotvp(Vel(bp), frame[i]);
      SETV(Vel(bp), tmpv);
    }
    if (AccField.offset != BadOffset) {
      for (i = 0; i < NDIM; i++)
	tmpv[i] = dotvp(Acc(bp), frame[i]);
      SETV(Acc(bp), tmpv);
    }
    if (AuxVecField.offset != BadOffset) {
      for (i = 0; i < NDIM; i++)
	tmpv[i] = dotvp(AuxVec(bp), frame[i]);
      SETV(AuxVec(bp), tmpv);
    }
  }
  for (i = 0; i < NDIM; i++)
    SETV(oldframe[i], frame[i]);
}    
Beispiel #8
0
void disconnect(bool async, bool cleanup)
{
    if(curpeer) 
    {
        if(!discmillis)
        {
            enet_peer_disconnect(curpeer, DISC_NONE);
            enet_host_flush(clienthost);
            discmillis = totalmillis;
        }
        if(curpeer->state!=ENET_PEER_STATE_DISCONNECTED)
        {
            if(async) return;
            enet_peer_reset(curpeer);
        }
        curpeer = NULL;
        discmillis = 0;
        conoutf("disconnected");
        game::gamedisconnect(cleanup);
        SETV(mainmenu, 1);
    }
    if(!connpeer && clienthost)
    {
        enet_host_destroy(clienthost);
        clienthost = NULL;
    }
}
Beispiel #9
0
void rotatevec(vector vec, matrix mat)
{
  vector tmp;
  
  MULMV(tmp, mat, vec);
  SETV(vec, tmp);
}
Beispiel #10
0
void hackgrav(bodyptr p, bool intree)
{
    pskip = p;					/* exclude p from f.c.      */
    SETV(pos0, PosB(p));				/* set field point          */
    phi0 = 0.0;					/* init total potential     */
    CLRV(acc0);					/* and total acceleration   */
    n2bterm = nbcterm = 0;			/* count body & cell terms  */
    skipself = FALSE;				/* watch for tree-incest    */
    treescan((nodeptr) &root->cellnode);			/* scan tree from root	    */
    if (intree && ! skipself) {			/* did tree-incest occur?   */
	if (! scanopt(options, "allow-incest"))	/*   treat as catastrophic? */
	    error("hackgrav: tree-incest detected\n");
	if (! treeincest)			/*   for the first time?    */
	    eprintf("\n[hackgrav: tree-incest detected]\n");
	treeincest = TRUE;			/*   don't repeat warning   */
    }
    Phi(p) = phi0;				/* store total potential    */
    SETV(Acc(p), acc0);				/* and acceleration         */
}
Beispiel #11
0
void write_snapshot(void)
{
    real *mbuf, *mp, *pspbuf, *pspp;
    bodyptr bp;
    int cs = CSCode(Cartesian, NDIM, 2);
    string options = getparam("options");

    mbuf = mp = (real *) allocate(ntest * sizeof(real));
    pspbuf = pspp = (real *) allocate(ntest * 2 * NDIM * sizeof(real));
    for (bp = testdata; bp < testdata+ntest; bp++) {
	*mp++ = Mass(bp);
	SETV(pspp, Pos(bp));
	pspp += NDIM;
	SETV(pspp, Vel(bp));
	pspp += NDIM;
    }
    put_set(outstr, SnapShotTag);
    put_set(outstr, ParametersTag);
    put_data(outstr, NobjTag, IntType, &ntest, 0);
    put_data(outstr, TimeTag, RealType, &tsnap, 0);
    put_data(outstr, "tol", RealType, &tol, 0);
    put_data(outstr, "eps", RealType, &eps, 0);
    put_tes(outstr, ParametersTag);
    put_set(outstr, ParticlesTag);
    put_data(outstr, CoordSystemTag, IntType, &cs, 0);
    if (scanopt(options, "mass"))
	put_data(outstr, MassTag, RealType, mbuf, ntest, 0);
    if (scanopt(options, "phase"))
	put_data(outstr, PhaseSpaceTag, RealType, pspbuf, ntest, 2, NDIM, 0);
    put_data(outstr, PotentialTag, RealType, phidata, ntest, 0);
    put_data(outstr, AccelerationTag, RealType, accdata, ntest, NDIM, 0);
    put_tes(outstr, ParticlesTag);
    put_set(outstr, DiagnosticsTag);
    put_data(outstr, "n2btot", IntType, &n2btot, 0);
    put_data(outstr, "nbctot", IntType, &nbctot, 0);
    put_data(outstr, "cputree", RealType, &cputree, 0);
    put_data(outstr, "cpufcal", RealType, &cpufcal, 0);
    put_tes(outstr, DiagnosticsTag);
    put_tes(outstr, SnapShotTag);
    free(mbuf);
    free(pspbuf);
}
Beispiel #12
0
void walkTree(nodeptr * aPtr, nodeptr *nPtr,
	cellptr cPtr, cellptr bPtr,
	nodeptr p, real pSize, vector pMid, double eps)
{
	nodeptr *np, *ap, q;
	int activeSafe;

	/* Are new forces needed? */
	if (Update(p)) {
		/* Start new active list */
		np = nPtr;
		/* Loop over active nodes   */
		for (ap = aPtr; ap < nPtr; ap++) {
			/* Is this node a cell?     */
			if (Type(*ap) == CELL) {
				/* If the node pass the test */
				if (acceptNode(*ap, pSize, pMid)) {
					/* If the node contribute to the field */
					if (Mass(*ap) > 0.0) {
						/* Copy to interaction list */
						Mass(cPtr) = Mass(*ap);
						SETV(Pos(cPtr), Pos(*ap));
						/* Next interaction element */
						cPtr++;
					}
				} else { /* If not accepted */
					for (q = More(*ap); q != Next(*ap); q = Next(q))
						*np++ = q;
				}
			} else {/* If this node is a body */
				/* If it's not self-interaction */
				if (*ap != p && Mass(*ap) > 0.0) {
					/* Build interaction element */
					--bPtr;
					/* Copy data to array */
					Mass(bptr) = Mass(*ap);
					SETV(Pos(bPtr), Pos(*ap));
				}
			}
		}
	}
}
Beispiel #13
0
local void gravsum(bodyptr p0, cellptr cptr, cellptr bptr)
{
  vector pos0, acc0;
  real phi0;
 
  SETV(pos0, Pos(p0));                          // copy position of body
  phi0 = 0.0;                                   // init total potential
  CLRV(acc0);                                   // and total acceleration
  if (usequad)                                  // if using quad moments
    sumcell(interact, cptr, pos0, &phi0, acc0); // sum cell forces w quads
  else                                          // not using quad moments
    sumnode(interact, cptr, pos0, &phi0, acc0); // sum cell forces wo quads
  sumnode(bptr, interact + actmax, pos0, &phi0, acc0);
                                                // sum forces from bodies
  Phi(p0) = phi0;                               // store total potential
  SETV(Acc(p0), acc0);                          // and total acceleration
  nfcalc++;                                     // update counters
  nbbcalc += interact + actmax - bptr;
  nbccalc += cptr - interact;
}
Beispiel #14
0
local void walkgrav(nodeptr *aptr, nodeptr *nptr, cellptr cptr, cellptr bptr,
                    nodeptr p, real psize, vector pmid)
{
    nodeptr *np, *ap, q;
    int actsafe;
 
    if (Update(p)) {				/* are new forces needed?   */
	np = nptr;				/* start new active list    */
	actsafe = actlen - NSUB;                /* leave room for NSUB more */
	for (ap = aptr; ap < nptr; ap++)        /* loop over active nodes   */
	    if (Cell(*ap)) {                    /* is this node a cell?     */
		if (accept(*ap, psize, pmid)) {	/* does it pass the test?   */
		    Mass(cptr) = Mass(*ap);	/* copy to interaction list */
		    SETV(Pos(cptr), Pos(*ap));
		    SETM(Quad(cptr), Quad(*ap));
		    cptr++;			/* and bump cell array ptr  */
		} else {			/* else it fails the test   */
		    if (np - active >= actsafe) /* check list has room      */
			error("walkgrav: active list overflow\n");
		    for (q = More(*ap); q != Next(*ap); q = Next(q))
						/* loop over all subcells   */
			*np++= q;               /* put on new active list   */
		}
	    } else                              /* else this node is a body */
		if (*ap != p) {                 /* if not self-interaction  */
		    --bptr;			/* bump body array ptr      */
		    Mass(bptr) = Mass(*ap);	/* and copy data to array   */
		    SETV(Pos(bptr), Pos(*ap));
		}
	actmax = MAX(actmax, np - active);	/* keep track of max active */
	if (np != nptr)                         /* if new actives listed    */
	    walksub(nptr, np, cptr, bptr, p, psize, pmid);
						/* then visit next level    */
	else {                                  /* else no actives left, so */
	    if (! Body(p))                      /* must have found a body   */
		error("walkgrav: recursion terminated with cell\n");
	    gravsum((bodyptr) p, cptr, bptr);   /* sum force on the body    */
	}
    }
}
Beispiel #15
0
local void gravsum(bodyptr p0, cellptr cptr, cellptr bptr)
{
    vector pos0, acc0;
    real phi0;
 
    SETV(pos0, Pos(p0));                        /* copy position of body    */
    phi0 = 0.0;                                 /* init total potential     */
    CLRV(acc0);                                 /* and total acceleration   */
    if (usequad)                                /* if using quad moments    */
        sumcell(interact, cptr, pos0, &phi0, acc0);
                                                /* sum cell forces w quads  */
    else                                        /* not using quad moments   */
        sumnode(interact, cptr, pos0, &phi0, acc0);
                                                /* sum cell forces wo quads */
    sumnode(bptr, interact + actlen, pos0, &phi0, acc0);
                                                /* sum forces from bodies   */
    Phi(p0) = phi0;                             /* store total potential    */
    SETV(Acc(p0), acc0);                        /* and total acceleration   */
    nfcalc++;                                   /* update counters          */
    nbbcalc += interact + actlen - bptr;
    nbccalc += cptr - interact;
}
Beispiel #16
0
void force_calc(void)
{
    real *pp, *ap;
    double cpubase;
    string *rminxstr;
    int i;
    bodyptr bp;

    tol = getdparam("tol");
    eps = getdparam("eps");
    rsize = getdparam("rsize");
    rminxstr = burststring(getparam("rmin"), ", ");
    if (xstrlen(rminxstr, sizeof(string)) < NDIM) {
	SETVS(rmin, - rsize / 2.0);
    } else
	for (i = 0; i < NDIM; i++)
	    rmin[i] = atof(rminxstr[i]);
    dprintf(0,"initial rsize: %8f    rmin: %8f  %8f  %8f\n",
	   rsize, rmin[0], rmin[1], rmin[2]);
    fcells = getdparam("fcells");
    phidata = pp = (real *) allocate(ntest * sizeof(real));
    accdata = ap = (real *) allocate(ntest * NDIM * sizeof(real));
    cpubase = cputime();
    maketree(massdata, nmass);
    cputree = cputime() - cpubase;
    dprintf(0,"  final rsize: %8f    rmin: %8f  %8f  %8f\n",
	   rsize, rmin[0], rmin[1], rmin[2]);
    cpubase = cputime();
    n2btot = nbctot = 0;
    for (bp = testdata; bp < testdata+ntest; bp++) {
	hackgrav(bp);
	*pp++ = Phi(bp);
	SETV(ap, Acc(bp));
	ap += NDIM;
	n2btot += n2bterm;
	nbctot += nbcterm;
    }
    cpufcal = cputime() - cpubase;
}
Beispiel #17
0
void TargetingControl::determineMouseTarget(bool forceEntityCheck)
{
    TargetingControl::worldPosition = worldpos;

    if (Logging::shouldShow(Logging::INFO))
        particle_splash(0, 50, 100, TargetingControl::worldPosition); // Kripken: Show some sparkles where the mouse points - for debug

    if (!useMouseTargeting && !editmode && !forceEntityCheck)
    {
        TargetingControl::targetLogicEntity = placeholderLogicEntity;
        TargetingControl::targetPosition = TargetingControl::worldPosition;
        SETV(has_mouse_target, 0);
    } else {
        static long lastEntityCheck = -1; // Use this to not run an actual entity check more than 1/frame

        if (lastEntityCheck != lastmillis)
        {
            float dist;

            TargetingControl::intersectClosest(camera1->o,
                                               worldpos,
                                               camera1,
                                               dist,
                                               TargetingControl::targetLogicEntity);

            // If not edit mode, ignore the player itself
            if (!editmode && TargetingControl::targetLogicEntity.get() && !TargetingControl::targetLogicEntity->isNone() &&
                TargetingControl::targetLogicEntity->getUniqueId() == ClientSystem::uniqueId)
            {
                // Try to see if the player was the sole cause of collision - move it away, test, then move it back
                vec save = ClientSystem::playerLogicEntity->dynamicEntity->o;
                ClientSystem::playerLogicEntity->dynamicEntity->o.add(10000.0);

                TargetingControl::intersectClosest(camera1->o,
                                                   worldpos,
                                                   camera1,
                                                   dist,
                                                   TargetingControl::targetLogicEntity);

                ClientSystem::playerLogicEntity->dynamicEntity->o = save;
            }

            SETV(has_mouse_target, int(TargetingControl::targetLogicEntity.get() && !TargetingControl::targetLogicEntity->isNone()));

            if (GETIV(has_mouse_target))
            {
                vec temp(worldpos);
                temp.sub(camera1->o);
                temp.normalize();
                temp.mul(dist);
                temp.add(camera1->o);

                TargetingControl::targetPosition = temp;
            } else
                TargetingControl::targetPosition = TargetingControl::worldPosition;

            lastEntityCheck = lastmillis;
        }
    }

//    if (!placeholderLogicEntity.get()->isNone())
//        TargetingControl::targetLogicEntity = LogicSystem::getLogicEntity(placeholderLogicEntity.get()->getUniqueId());
//    else
//        TargetingControl::targetLogicEntity = placeholderLogicEntity;
}
Beispiel #18
0
 void showscores(bool on)
 {
     SETV(scoreboard, on ? 1 : 0);
     scoreboard.show(on);
 }
Beispiel #19
0
plotsnap()
{
    real t, *mp, *psp, *pp, *ap, *acp;
    int vismax, visnow, i, vis, icol;
    real psz, col, x, y, z;
    Body b;
    bool Qall = FALSE;

    t = (timeptr != NULL ? *timeptr : 0.0);	/* get current time value   */
    CLRV(Acc(&b));				/* zero unsupported fields  */
    Key(&b) = 0;
    visnow = vismax = 0;
    do {					/* loop painting layers     */
	visnow++;				/*   make next layer visib. */
	mp  = massptr;				/*   (re)set data pointers  */
	psp = phaseptr;
	pp  = phiptr;
	ap  = auxptr;
	acp = accptr;
	npnt = 0;
	for (i = 0; i < nbody; i++) {		/*   loop over all bodies   */
	    Mass(&b) = (mp != NULL ? *mp++ : 0.0);
						/*     set mass if supplied */
	    SETV(Pos(&b), psp);			/*     always set position  */
	    psp += NDIM;			/*     and advance p.s. ptr */
	    SETV(Vel(&b), psp);			/*     always set velocity  */
	    psp += NDIM;			/*     and advance ptr      */
	    Phi(&b) = (pp != NULL ? *pp++ : 0.0);	
	    Aux(&b) = (ap != NULL ? *ap++ : 0.0);
	    if (acp) {				
	    	SETV(Acc(&b),acp);		/*     set accel's          */	
	    	acp += NDIM;			/*     and advance ptr      */
	    }
	    					/*     set phi,aux if given */
	    vis = (*vfunc)(&b, t, i);		/*     evaluate visibility  */
	    vismax = MAX(vismax, vis);		/*     remember how hi to go*/
	    if (vis == visnow) {		/*     if body is visible   */
	        x = (*xfunc)(&b, t, i);	        /*     evaluate x,y,z coords*/
		y = (*yfunc)(&b, t, i);
		z = (*zfunc)(&b, t, i);

		psz = (*pfunc)(&b, t, i);
#define MAXCOLOR 16
#ifdef COLOR
		col = (*cfunc)(&b, t, i);
		col = (col - crange[0])/(crange[1] - crange[0]);
		icol = 1 + (MAXCOLOR - 2) * MAX(0.0, MIN(1.0, col));
		s2sci(icol);
#endif
		xpnt[npnt] = x;
		ypnt[npnt] = y;
		zpnt[npnt] = z;
		if (!Qall) {
		  s2pt1(xpnt[npnt],ypnt[npnt],zpnt[npnt], visnow);
		}
		npnt++;
	    }
	} /* i<nbody */
	if (Qall)
	  s2pt(npnt, xpnt, ypnt, zpnt, visnow);
    } while (visnow < vismax);			/* until final layer done   */
}