warp.c 20.09 KiB
#ifdef USE_WARP
/*
* Time-dependent warp of a particle field,
* for fake differentially-rotating galaxies.
* Stuart Levy, slevy@ncsa.uiuc.edu
* National Center for Supercomputing Applications,
* University of Illinois 2001.
* This file is part of partiview, released under the
* Illinois Open Source License; see the file LICENSE.partiview for details.
*/
#ifdef WIN32
# include "winjunk.h"
#endif
#if unix
# include <unistd.h>
#endif
#include <stdlib.h>
#include <math.h>
#include "shmem.h"
#include "specks.h"
#include "partiviewc.h"
#include "textures.h" /* for get_dsp_context() */
static char local_id[] = "$Id$";
struct speckcache {
float tfrac;
struct specklist *sl;
};
#define COORD_DISK 0
#define COORD_WORLD (-1)
#define COORD_OBJECT (-2)
struct warpstuff {
float tfrom, tto;
float zerotime;
int has_trange, has_zerotime;
float period0;
float rcore, routercore;
int core_coordsys;
float rcoredisk, routercoredisk;
double fixedp[3];
float rfixed;
int has_fixed, fixed_coordsys;
float fixedrdisk;
float rigidrot;
double d2o[16], o2d[16];
int has_d2o, has_o2d;
int valid;
int locked;
float tfrac, dtfrac;
double realtime;
float fixomega;
struct speckcache slc[MAXDSPCTX];
};
extern float fastsin2pi( float v );
static void inittables(void);
struct specklist *warp_get_parti( struct dyndata *dd, struct stuff *st, double realtime );
int warp_get_trange( struct dyndata *dd, struct stuff *st, double *tminp, double *tmaxp );
int warp_parse_args( struct dyndata *dd, struct stuff *st, int argc, char **argv );
struct warpstuff *warp_setup( struct warpstuff *ws, int argc, char **argv );
static int warp_coordsys( const char *str ) {
if(strchr(str, 'w')) return COORD_WORLD;
if(strchr(str, 'o')) return COORD_OBJECT;
if(strchr(str, 'd')) return COORD_DISK;
return COORD_DISK;
}
int parsematrix( double tfm[16], char *str, const char *whose )
{
double m[16];
Matrix T;
Point xyz;
float aer[3];
float scl = 1.0;
int k = sscanf(str,
"%lf%*c%lf%*c%lf%*c%lf%*c%lf%*c%lf%*c%lf%*c%lf%*c%lf%*c%lf%*c%lf%*c%lf%*c%lf%*c%lf%*c%lf%*c%lf",
&m[0],&m[1],&m[2],&m[3],
&m[4],&m[5],&m[6],&m[7],
&m[8],&m[9],&m[10],&m[11],
&m[12],&m[13],&m[14],&m[15]);
switch(k) {
case 1: /* simple scaling */
memset(tfm, 0, 16*sizeof(double));
tfm[0*4+0] = tfm[1*4+1] = tfm[2*4+2] = m[0];
tfm[3*4+3] = 1;
return 1;
case 7: /* virdir style Tx Ty Tz Rx Ry Rz Scl */
scl = m[6]; /* and fall into ... */
case 6: /* virdir style Tx Ty Tz Rx Ry Rz */
xyz.x[0] = m[0];
xyz.x[1] = m[1];
xyz.x[2] = m[2];
aer[1] = m[3];
aer[0] = m[4];
aer[2] = m[5];
xyzaer2tfm( &T, &xyz, aer );
for(k = 0; k < 3*4; k++)
tfm[k] = T.m[k] * scl;
for(k = 3*4; k < 4*4; k++)
tfm[k] = T.m[k];
return 1;
case 9: /* 3x3 linear */
memset(tfm, 0, 16*sizeof(double));
for(k = 0; k < 3; k++) {
tfm[k*4+0] = m[k*3+0];
tfm[k*4+1] = m[k*3+1];
tfm[k*4+2] = m[k*3+2];
}
tfm[3*4+3] = 1;
return 1;
case 16:
memcpy(tfm, m, 16*sizeof(double));
break; /* great */
default:
if(whose)
msg("%s %s: expected 1 or 6 or 7 or 9 or 16 numbers", whose, str);
return 0;
}
return 1;
}
struct warpstuff *warp_setup( struct warpstuff *oldws, int argc, char **argv )
{
struct warpstuff *ws;
struct warpstuff tws;
int i, c;
char key;
float v;
inittables();
if(oldws)
tws = *oldws;
else
memset(&tws, 0, sizeof(tws));
for(i = 1; i < argc-1; i += 2) {
char *optarg = argv[i+1];
if(!strcmp(argv[i], "-p")) {
sscanf(optarg, "%f", &tws.period0);
} else if(!strcmp(argv[i], "-f")) {
tws.has_trange = sscanf(optarg,"%f%*c%f",&tws.tfrom,&tws.tto);
} else if(!strcmp(argv[i], "-z")) {
tws.has_zerotime = sscanf(optarg, "%f", &tws.zerotime);
} else if(!strcmp(argv[i], "-t")) {
sscanf(optarg, "%f%*c%f", &tws.tfrac, &tws.dtfrac);
} else if(!strncmp(argv[i], "-fix", 4)) {
tws.has_fixed = 0;
tws.fixed_coordsys = warp_coordsys( optarg );
switch(sscanf(optarg, "%lf%*c%lf%*c%lf",
&tws.fixedp[0], &tws.fixedp[1], &tws.fixedp[2])) {
case 1: tws.has_fixed = 1; break;
case 3: tws.has_fixed = 3; break;
default:
msg("warp -fix {x,y,z|radius}[w] not %s", optarg);
}
} else if(!strcmp(argv[i], "-r")) {
tws.core_coordsys = warp_coordsys( optarg );
switch(sscanf(optarg, "%f%c%f", &tws.rcore, &key, &v)) {
case 3:
if(key == '-') tws.routercore = v;
else tws.routercore = tws.rcore*(1+v);
break;
case 1:
tws.routercore = tws.rcore * 1.1;
break;
default:
argc = 0;
}
} else if(!strcmp(argv[i], "-T")) {
tws.has_o2d = parsematrix( tws.o2d, optarg, "warp -T" );
} else if(!strcmp(argv[i], "-F")) {
tws.has_d2o = parsematrix( tws.d2o, optarg, "warp -F" );
} else if(!strcmp(argv[i], "-rigidrot") || !strcmp(argv[i], "-R")) {
sscanf(optarg, "%g", &tws.rigidrot); /* given as degrees */
tws.rigidrot /= 360; /* internally, kept as fraction of 1 turn */
} else {
argc = -1;
break;
}
}
if(argc < 3) {
msg("Usage: %s [-f fin,fout][-p period0][-z zerotime][-R rot][-T o2d][-F d2o] [-r rcore[,transition][w]]] [-fix x,y,z[w]|radius[w]]", argv[0]);
msg("-r : core rad. w/optional width of transition region (fraction of rcore)");
msg(" : or (\"-\" separator) -r innercore-outercore");
msg("-R(or -rigidrot) : add rigid rotation by \"rot\" degrees to entire body.");
msg("-T, -F sixteen numbers. If only -T or -F is given, other is computed.");
msg(" \"o2d\" = object-to-disk tfm, where disk center=0,0,0, in XZ plane.");
msg("-fix x,y,z[w] or -fix r[w] (fix point or radius); \"w\" = \"world coords\".");
msg(" sense: p' = p * o2d * warp(X,Z plane) * d2o");
return NULL;
}
ws = oldws ? oldws : NewN( struct warpstuff, 1 );
*ws = tws;
ws->valid = 0; /* Force recomputing parameters */
return ws;
}
float slerp( float frac, float from, float to )
{
if(frac<=0) return from;
if(frac>=1) return to;
return from + frac*frac*(3-2*frac)*(to-from);
}
void windup( struct warpstuff *ws, Point *out, CONST Point *in )
{
/*
* v(r) = (vmax/rcore)*r r in 0..rcore
* vmax r > rcore
* period(r) = 2pi/(vmax/rcore) r<rcore [Call this T0.]
* 2pi/(vmax/r) = (r/rcore)*T0
* theta(t/T0,r) = (t/T0)*T0*(r < rcore ? 1 : rcore/r)
* So rotate in the XZ plane about (0,0,0) by theta(t/T0,r)
*/
float x = in->x[0];
float z = in->x[2];
float r = hypotf( x, z );
float omega = (r<=ws->rcoredisk) ? 1
: (r>=ws->routercoredisk) ? ws->routercoredisk/r
: slerp( 1+(r-ws->routercoredisk)/(ws->routercoredisk-ws->rcoredisk),
1, ws->routercoredisk/r );
float theta, s, c;
theta = (omega - ws->fixomega) * ws->tfrac + ws->rigidrot;
s = fastsin2pi( theta );
c = fastsin2pi( theta + 0.25 );
out->x[0] = x*c - z*s;
out->x[1] = in->x[1];
out->x[2] = x*s + z*c;
}
void dvtfmpoint( Point *dst, CONST Point *src, CONST double T[16] )
{
int i;
for(i = 0; i < 3; i++)
dst->x[i] = src->x[0]*T[i] + src->x[1]*T[i+4] + src->x[2]*T[i+8] + T[i+12];
}
void windup_o2d( struct warpstuff *ws, Point *out, CONST Point *in ) {
Point tin, tout;
dvtfmpoint( &tin, in, ws->o2d );
windup( ws, &tout, &tin );
dvtfmpoint( out, &tout, ws->d2o );
}
void warpspecks( struct warpstuff *ws,
struct stuff *st,
struct specklist *osl,
struct specklist *sl )
{
struct speck *osp, *sp;
int i, n;
if(osl->specks == NULL) return;
n = osl->nspecks;
/* memcpy( sl->specks, osl->specks, osl->bytesperspeck * n ); */
osp = osl->specks;
sp = sl->specks;
for(i = 0; i < n; i++) {
if(ws->has_o2d)
windup_o2d( ws, &sp->p, &osp->p );
else
windup( ws, &sp->p, &osp->p );
osp = NextSpeck(osp, osl, 1);
sp = NextSpeck(sp, sl, 1);
}
}
static float warpfrac( struct warpstuff *ws, double time )
{
if(ws->has_trange == 2 && ws->tfrom != ws->tto) {
return slerp( (time - ws->tfrom) / (ws->tto - ws->tfrom), -1, 1 );
} else if(ws->period0 != 0) {
return 2 * (time - ws->tfrom) / ws->period0 - 1;
} else {
return 0;
}
}
static double dvlength( double v[3] ) {
return sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] );
}
static void ddmmul( double dest[16], Matrix *a, double b[16] ) {
int i,j;
for(i = 0; i < 4; i++) {
for(j = 0; j < 4; j++) {
dest[i*4+j] = a->m[i*4+0]*b[0*4+j]
+ a->m[i*4+1]*b[1*4+j]
+ a->m[i*4+2]*b[2*4+j]
+ a->m[i*4+3]*b[3*4+j];
}
}
}
static void dvmmul( double dest[3], double src[3], double T[16] ) {
double w = src[0]*T[0*4+3] + src[1]*T[1*4+3] + src[2]*T[2*4+3] + T[3*4+3];
w = 1/w;
dest[0] = (src[0]*T[0*4+0] + src[1]*T[1*4+0] + src[2]*T[2*4+0] + T[3*4+0])*w;
dest[1] = (src[0]*T[0*4+1] + src[1]*T[1*4+1] + src[2]*T[2*4+1] + T[3*4+1])*w;
dest[2] = (src[0]*T[0*4+2] + src[1]*T[1*4+2] + src[2]*T[2*4+2] + T[3*4+2])*w;
}
static int getT2d( double T2d[16], struct stuff *st, struct warpstuff *ws, int coordsys )
{
Matrix o2w, w2o;
switch(coordsys) {
case COORD_DISK:
return 0;
case COORD_OBJECT:
if(!ws->has_o2d)
return 0;
memcpy( T2d, ws->o2d, 16*sizeof(double) );
return 1;
case COORD_WORLD:
parti_geto2w( st, parti_idof(st), &o2w );
eucinv( &w2o, &o2w );
if(ws->has_o2d) {
ddmmul( T2d, &w2o, ws->o2d );
} else {
int i;
for(i = 0; i < 4*4; i++)
T2d[i] = w2o.m[i];
}
return 1;
}
msg("warp getT2d %d", coordsys);
return 0;
}
static double rtodisk( struct stuff *st, struct warpstuff *ws, double radius, int coordsys ) {
double w2d[16];
switch(coordsys) {
case COORD_DISK:
return radius;
case COORD_OBJECT:
return (ws->has_o2d ? radius * dvlength( &ws->o2d[0] ) : radius);
case COORD_WORLD:
getT2d( w2d, st, ws, COORD_WORLD );
return radius * dvlength( &w2d[0] );
}
msg("warp: rtodisk");
return 0;
}
/* Delay computing transformable quantities until we really need them */
static void setup_coords( struct stuff *st, struct warpstuff *ws ) {
double fixed2d[16];
double fixedpdisk[3];
if(!ws->valid) {
ws->rcoredisk = rtodisk( st, ws, ws->rcore, ws->core_coordsys );
ws->routercoredisk = rtodisk( st, ws, ws->routercore, ws->core_coordsys );
switch(ws->has_fixed) {
case 1:
ws->fixedrdisk = rtodisk( st, ws, ws->fixedp[0], ws->fixed_coordsys );
break;
case 3:
if(getT2d( fixed2d, st, ws, ws->fixed_coordsys )) {
dvmmul( fixedpdisk, ws->fixedp, fixed2d );
ws->fixedrdisk = hypot( fixedpdisk[0], fixedpdisk[2] );
} else {
ws->fixedrdisk = hypot( ws->fixedp[0], ws->fixedp[2] );
}
break;
}
ws->valid = 1;
}
if(ws->has_fixed) {
ws->fixomega =
(ws->fixedrdisk <= ws->rcoredisk) ? 1
: (ws->fixedrdisk >= ws->routercoredisk) ?
ws->routercoredisk / ws->fixedrdisk
: slerp( 1 + (ws->fixedrdisk - ws->routercoredisk)
/ (ws->routercoredisk - ws->rcoredisk),
1, ws->routercoredisk / ws->fixedrdisk );
} else {
ws->fixomega = 0;
}
}
#define MAXINTERP 1024
float sintbl[MAXINTERP+1];
static void inittables(void) {
int i;
for(i = 0; i <= MAXINTERP; i++)
sintbl[i] = sinf(2*M_PI*i / MAXINTERP);
}
/* fastsin2pi( x ) returns approximately sin( 2*pi*x ),
* i.e. sin(x) if x is given as a fraction of a full 360-degree turn.
*/
float fastsin2pi( float v ) {
int i;
while(v < 0) v += 1;
while(v > 1) v -= 1;
v *= MAXINTERP;
i = (int)v;
return sintbl[i] + (v - i)*(sintbl[i+1]-sintbl[i]);
}
void deucinv( double dst[16], CONST double src[16] )
{
int i, j;
double s = src[0]*src[0] + src[1]*src[1] + src[2]*src[2];
Point trans;
double t[16];
if(src == dst) {
memcpy( t, src, sizeof(t) );
src = t;
}
for(i = 0; i < 3; i++) {
for(j = 0; j < 3; j++)
dst[i*4+j] = src[j*4+i] / s;
dst[i*4+3] = 0;
}
for(i = 0; i < 3; i++)
dst[3*4+i] = -(src[3*4+0]*dst[0*4+i] + src[3*4+1]*dst[1*4+i] + src[3*4+2]*dst[2*4+i]);
dst[3*4+3] = 1;
}
#ifndef STANDALONE
int warp_parse_args( struct dyndata *dd, struct stuff *st, int argc, char **argv )
{
struct warpstuff *ws;
if(argc < 1 || 0!=strcmp(argv[0], "warp"))
return 0;
if(dd == NULL || (ws = (struct warpstuff *)dd->data) == NULL) {
msg("No warp enabled");
return 1;
}
if(argc>1 && (!strcmp(argv[1], "lock") || !strcmp(argv[1], "off"))) {
ws->locked = 1;
} else if(argc>1 && (!strcmp(argv[1], "unlock") || !strcmp(argv[1], "on"))) {
ws->valid = 0; /* force recomputing */
ws->locked = 0;
}
msg("warp %stfrac %g at time %g fixp %g %g %g rfixd %g fixsys %d rcored %g",
ws->locked ? "locked " : "",
ws->tfrac, ws->realtime,
ws->fixedp[0],ws->fixedp[1],ws->fixedp[2], ws->fixedrdisk, ws->fixed_coordsys, ws->rcoredisk);
return 1;
}
int warp_get_trange( struct dyndata *dd, struct stuff *st, double *tminp, double *tmaxp )
{
*tminp = -10000;
*tmaxp = 10000;
return 1;
}
static void scrapsl( struct specklist **slp ) {
struct specklist *sl, *slnext;
if(slp == NULL) return;
sl = *slp;
*slp = NULL;
for( ; sl; sl = slnext) {
slnext = sl->next;
if(sl->specks) Free(sl->specks);
Free(sl);
}
}
int warp_read( struct stuff **stp, int argc, char *argv[], char *fname, void *etc ) {
struct stuff *st = *stp;
struct warpstuff *ws;
if(argc < 1 || strcmp(argv[0], "warp") != 0)
return 0;
st->clk->continuous = 1;
if(st->dyn.ctlcmd == warp_parse_args) {
ws = (struct warpstuff *)st->dyn.data;
} else {
ws = NULL;
}
ws = warp_setup( ws, argc, argv );
if(ws == NULL)
return 0;
memset(&st->dyn, 0, sizeof(st->dyn));
st->dyn.data = ws;
st->dyn.getspecks = warp_get_parti;
st->dyn.trange = warp_get_trange;
st->dyn.ctlcmd = warp_parse_args;
st->dyn.draw = NULL;
st->dyn.free = NULL;
st->dyn.enabled = 1;
return 1;
}
void warp_init() {
parti_add_reader( warp_read, "warp", NULL );
}
struct specklist *
warp_get_parti( struct dyndata *dd, struct stuff *st, double realtime )
{
struct warpstuff *ws = (struct warpstuff *)dd->data;
int ctx = get_dsp_context();
struct speckcache *sc = &ws->slc[ctx];
struct specklist *sl, *osl, **slp;
static int once = 1;
#if unix
if(once-- == 0 && getenv("DBG")) {
fprintf(stderr, "warp_get_parti: dbx -p %d\n", getpid());
sleep(atoi(getenv("DBG")));
}
#endif
if(ws->locked && ws->valid && sc != NULL)
return sc->sl;
setup_coords( st, ws ); /* bind coordsys-related stuff now */
ws->realtime = realtime;
ws->tfrac = warpfrac(ws, realtime * 30);
if(ws->has_zerotime)
ws->tfrac -= warpfrac(ws, ws->zerotime);
if(ws->has_trange && ws->period0 != 0)
ws->tfrac *= (ws->tto - ws->tfrom) / ws->period0;
if(ws->has_o2d && !ws->has_d2o) {
deucinv( ws->d2o, ws->o2d );
ws->has_d2o = -1;
} else if(!ws->has_o2d && ws->has_d2o) {
deucinv( ws->o2d, ws->d2o );
ws->has_o2d = -1;
}
if(getenv("WDBG")) printf("%g %g %g # rt frac frac(rt)\n", realtime, ws->tfrac, warpfrac(ws, realtime*30));
if(sc->sl != NULL && sc->tfrac == ws->tfrac)
return sc->sl;
osl = specks_timespecks( st, 0, 0 );
slp = &sc->sl;
for(sl = *slp; osl != NULL; osl = osl->next, slp = &sl->next, sl = *slp) {
if(sl == NULL || sl->speckseq != osl->speckseq) {
scrapsl(slp);
sl = NewN( struct specklist, 1 );
*sl = *osl;
sl->specks = NULL;
sl->next = NULL;
if(osl->specks) {
int len = osl->bytesperspeck * osl->nspecks;
sl->specks = (struct speck *)NewN( char, len );
memcpy( sl->specks, osl->specks, len );
}
*slp = sl;
}
warpspecks( ws, st, osl, sl );
}
sc->tfrac = ws->tfrac;
return sc->sl;
}
#else /*STANDALONE*/
#include <stdarg.h>
#include "stardef.h"
int msg( CONST char *fmt, ... ) {
char str[10240];
va_list args;
va_start(args, fmt);
vsprintf(str, fmt, args);
va_end(args);
return fprintf(stderr, "%s\n", str);
}
int parti_idof( struct stuff *stjunk ) {
return 1;
}
void parti_geto2w( struct stuff *stjunk, int objid, Matrix *o2w ) {
int k;
char *tfm = getenv("tfm");
Matrix T;
Point xyz;
float aer[3], scl;
if(tfm == NULL) {
msg("warpsdb: need object-to-world transform, but no \"tfm\" env variable set?");
exit(1);
}
k = sscanf(tfm,
"%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f",
&T.m[0], &T.m[1], &T.m[2], &T.m[3],
&T.m[4], &T.m[5], &T.m[6], &T.m[7],
&T.m[8], &T.m[9], &T.m[10], &T.m[11],
&T.m[12], &T.m[13], &T.m[14], &T.m[15]);
scl = 1;
switch(k) {
case 1:
scl = T.m[0];
mscaling( o2w, scl,scl,scl );
break;
case 7:
scl = T.m[6]; /* and fall into... */
case 6:
xyz.x[0] = T.m[0]; xyz.x[1] = T.m[1]; xyz.x[2] = T.m[2];
aer[1] = T.m[3]; aer[0] = T.m[4]; aer[2] = T.m[5];
xyzaer2tfm( &T, &xyz, aer );
if(scl == 1) {
*o2w = T;
} else {
Matrix Ts;
mscaling( &Ts, scl,scl,scl );
mmmul( o2w, &Ts, &T );
}
break;
case 16:
*o2w = T;
break;
default:
msg("warpsdb: \"tfm\"=%s; expected 1 or 6 or 7 or 16 numbers", tfm);
exit(1);
}
}
void dwindup( struct warpstuff *ws, float *xyzout, float *dxyzout, CONST float *xyz )
{
/*
* v(r) = (vmax/rcore)*r r in 0..rcore
* vmax r > rcore
* period(r) = 2pi/(vmax/rcore) r<rcore [Call this T0.]
* 2pi/(vmax/r) = (r/rcore)*T0
* theta(t/T0,r) = (t/T0)*T0*(r < rcore ? 1 : rcore/r)
* So rotate in the XZ plane about (0,0,0) by theta(t/T0,r)
*/
float x = xyz[0];
float z = xyz[2];
float r = hypot( x, z );
float omega = ( (r<=ws->rcoredisk) ? 1
: (r>=ws->routercoredisk) ? ws->routercoredisk/r
: slerp( 1 + (r-ws->routercoredisk)/(ws->routercoredisk-ws->rcoredisk),
1, ws->routercoredisk/r )
) - ws->fixomega;
float theta = omega * ws->tfrac + ws->rigidrot;
float dtheta = omega * ws->dtfrac * 2*M_PI;
float s = fastsin2pi( theta );
float c = fastsin2pi( theta + 0.25 );
xyzout[0] = x*c - z*s;
xyzout[1] = xyz[1];
xyzout[2] = x*s + z*c;
dxyzout[0] = -dtheta * (x*s + z*c);
dxyzout[1] = 0;
dxyzout[2] = dtheta * (x*c - z*s);
}
void dwindup_o2d( struct warpstuff *ws, float *xyzout, float *dxyzout, CONST float *xyz )
{
float v[3], w[3], dw[3];
int i;
for(i = 0; i < 3; i++)
v[i] = xyz[0]*ws->o2d[0*4+i] + xyz[1]*ws->o2d[1*4+i]
+ xyz[2]*ws->o2d[2*4+i] + ws->o2d[3*4+i];
dwindup( ws, w, dw, v );
for(i = 0; i < 3; i++) {
xyzout[i] = w[0]*ws->d2o[0*4+i] + w[1]*ws->d2o[1*4+i]
+ w[2]*ws->d2o[2*4+i] + ws->d2o[3*4+i];
dxyzout[i] = dw[0]*ws->d2o[0*4+i] + dw[1]*ws->d2o[1*4+i]
+ dw[2]*ws->d2o[2*4+i];
}
}
static void swabsdb( db_star *sp ) {
int i;
for(i = 0; i < 9; i++)
((int *)sp)[i] = htonl(((int *)sp)[i]); /* x,y,z...,num */
sp->color = htons(sp->color);
}
void warpsdb( struct warpstuff *ws, FILE *inf, FILE *outf ) {
static int one = 1;
int needswab = (*(char *)&one != 0);
int nstars = 0;
db_star star;
if(ws->has_o2d && !ws->has_d2o) {
deucinv( ws->d2o, ws->o2d );
ws->has_d2o = -1;
} else if(!ws->has_o2d && ws->has_d2o) {
deucinv( ws->o2d, ws->d2o );
ws->has_o2d = -1;
}
while(fread(&star, sizeof(star), 1, inf) > 0) {
float xyz[3];
nstars++;
if(needswab)
swabsdb(&star);
memcpy(xyz, &star.x, 3*sizeof(float));
if(ws->has_o2d)
dwindup_o2d( ws, &star.x, &star.dx, xyz );
else
dwindup( ws, &star.x, &star.dx, xyz );
if(needswab)
swabsdb(&star);
if(fwrite(&star, sizeof(star), 1, outf) <= 0) {
msg("Error writing star #%d", nstars);
break;
}
}
}
int main(int argc, char *argv[]) {
struct warpstuff *ws;
char *infname = NULL;
FILE *inf = stdin;
#define BIGBUFSIZE 2097152
char *obuf = (char *)malloc(BIGBUFSIZE);
char *ibuf = (char *)malloc(BIGBUFSIZE);
if(argc > 1 && 0==strcmp(&argv[argc-1][strlen(argv[argc-1])-4], ".sdb")) {
infname = argv[argc-1];
argc--;
inf = fopen(infname, "rb");
if(inf == NULL) {
msg("%s: %s: cannot open input", argv[0], infname);
exit(1);
}
}
setvbuf( inf, ibuf, _IOFBF, BIGBUFSIZE );
setvbuf( stdout, obuf, _IOFBF, BIGBUFSIZE );
ws = warp_setup( NULL, argc, argv );
if(ws == NULL)
exit(1); /* warp_setup() must have already printed a message */
setup_coords( NULL, ws );
if(ws->has_fixed && getenv("WARPDBG")) {
fprintf(stderr, "warp rcoredisk %g fixrdisk %g fixomega %g\n", ws->rcoredisk, ws->fixedrdisk, ws->fixomega);
}
warpsdb( ws, inf, stdout );
return 0;
}
#endif /*!STANDALONE*/
#endif /*USE_WARP*/