Newer
Older
* num (32-bit int),
* color (16-bit short).
* group and type fields shouldn't need swapping,
* assuming the compiler packs bytes into a word in increasing
* address order. Seems safe.
*/
if(*(char *)&one == 1) {
for(i = 0, wp = (int *)st; i < 10; i++)
wp[i] = htonl(wp[i]);
st->color = htons(st->color);
}
}
#else
#define starswap(x) /*nothing*/
#endif /*!WORDS_BIGENDIAN*/
static struct logTmap {
float logT;
unsigned short rgb565;
} tmap[] = {
// Adapted from Mitchell Charity's web page on black body RGB colors,
// http://www.vendian.org/mncharity/dir3/blackbody/
3.000, 0xf9c0, 3.079, 0xfa80, 3.204, 0xfb80, 3.301, 0xfc42,
3.380, 0xfce7, 3.477, 0xfdad, 3.556, 0xfe31, 3.643, 0xfed6,
3.716, 0xff5a, 3.792, 0xffbe, 3.869, 0xef7f, 3.944, 0xdf1f,
4.017, 0xcedf, 4.093, 0xbe9f, 4.164, 0xb67f, 4.236, 0xae5f,
4.310, 0xae3f, 4.380, 0xa61f, 4.450, 0xa5ff,
};
static unsigned short logT2rgb565(float logT) {
int i;
for(i = 0; i < COUNT(tmap)-1 && logT > tmap[i].logT; i++)
;
return tmap[i].rgb565;
}
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
static double sx=0, sy=0, sz=0, smass=0;
static int nspecks;
static int has_tfm;
static Point pmin, pmax;
static Matrix pT;
static void report( FILE *outf, struct dyndata *dyn, struct stuff *st )
{
double tmin, tmax;
kira_get_trange( &st->dyn, st, &tmin, &tmax );
fprintf(outf, "time %lg in %lg .. %lg\n",
curstate.realtime, tmin, tmax);
fprintf(outf, "nspecks %d\n", nspecks);
if(smass > 0) {
fprintf(outf, "CM %lg %lg %lg\n", sx/smass, sy/smass, sz/smass);
fprintf(outf, "bbox center %g %g %g radius %g %g %g\n",
.5*(pmax.x[0]+pmin.x[0]), .5*(pmax.x[1]+pmin.x[1]), .5*(pmax.x[2]+pmin.x[2]),
.5*(pmax.x[0]-pmin.x[0]), .5*(pmax.x[1]-pmin.x[1]), .5*(pmax.x[2]-pmin.x[2]));
Point cen;
kira_get_center( &cen, dyn, st );
fprintf(outf, "Center %g %g %g", cen.x[0],cen.x[1],cen.x[2]);
if(has_tfm) {
Point wcen;
vtfmpoint( &wcen, &cen, &pT );
fprintf(outf, " -> %g %g %g", wcen.x[0],wcen.x[1],wcen.x[2]);
}
fprintf(outf, "\n");
}
fprintf(outf, "transformation: out = in");
if(curstate.turnrate != 0)
fprintf(outf, " * %cRotation(%g*(time-%g))",
curstate.axis, curstate.turnrate, curstate.turntime0);
if(curstate.has_T0) {
float *fp = curstate.T0.m;
fprintf(outf, " * [%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g]",
fp[0],fp[1],fp[2],fp[3],
fp[4],fp[5],fp[6],fp[7],
fp[8],fp[9],fp[10],fp[11],
fp[12],fp[13],fp[14],fp[15]);
}
else if(curstate.turnrate == 0)
fprintf(outf, " (identity transform)");
fprintf(outf, "\n");
fprintf(outf, "group %d type %d\n", curstate.group, curstate.type);
}
float specklum( struct speck *sp ) {
return (curstate.masslum != 0) ? sp->val[SPECK_MASS]*sp->val[SPECK_MASS]*sp->val[SPECK_MASS]*curstate.masslum :
sp->val[SPECK_LUM];
}
int serveonce(char *req, FILE *outf)
{
int as_sdb = 0, as_speck = 0;
Point p;
db_star star;
char *cp;
struct stuff *st = curstate.st;
nspecks=0;
sx = sy = sz = smass = 0;
pmin.x[0]=pmin.x[1]=pmin.x[2] = 1e20;
pmax.x[0]=pmax.x[1]=pmax.x[2] = -1e20;
if(curstate.verbose)
fprintf(stdout, "REQ: %s\n", req);
if(outf == NULL || req == NULL) {
msg("kira server: get lost!");
if(outf) fclose(outf);
return 0;
}
if(strstr(req, "sdb")) as_sdb = 1;
else if(strstr(req, "speck")) as_speck = 1;
char *eqp;
for(eqp = req; (eqp = strchr(eqp, '=')) != NULL; ) {
char *optp, *argp;
for(optp = eqp; isalpha(optp[-1]); optp--)
;
argp = eqp+1;
cp = strpbrk(argp, ";&");
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
if(cp) {
eqp = cp+1;
*cp = '\0';
}
scanopt( optp, argp );
if(cp == NULL) break;
}
memset(&star, 0, sizeof(star));
star.group = curstate.group;
star.type = curstate.type;
struct specklist *sl;
sl = kira_get_parti( &st->dyn, st, curstate.realtime );
if(sl == NULL)
return 0;
has_tfm = curstate.has_T0 || curstate.turnrate != 0;
if(curstate.turnrate != 0) {
Matrix Trot;
mrotation( &Trot, curstate.turnrate * (curstate.realtime - curstate.turntime0), curstate.axis );
mmmul( &pT, &Trot, &curstate.T0 );
} else {
pT = curstate.T0;
nspecks = 0;
for(int i = 0; i < sl->nspecks; i++) {
struct speck *sp = NextSpeck(sl->specks, sl, i);
if(sp->val[SPECK_NCLUMP] < 0)
continue;
nspecks++;
Point vel, tvel;
vel.x[0] = sp->val[SPECK_SEPVEC] * curstate.dt;
vel.x[1] = sp->val[SPECK_SEPVEC+1] * curstate.dt;
vel.x[2] = sp->val[SPECK_SEPVEC+2] * curstate.dt;
if(has_tfm) {
vtfmpoint( &p, &sp->p, &pT );
vtfmpoint( &tvel, &vel, &pT );
vel = tvel;
} else {
p = sp->p;
}
if(as_sdb) {
star.x = p.x[0];
star.y = p.x[1];
star.z = p.x[2];
star.dx = vel.x[0]; // Use velocity,
star.dy = vel.x[1]; // held in SEPVEC
star.dz = vel.x[2]; // for leaf nodes.
star.magnitude = curstate.mag0 - .921 * logf( specklum(sp) );
if(curstate.colorscale >= 0) {
star.color = (unsigned short) (curstate.colorscale * sp->val[SPECK_TLOG]);
} else {
/* packed rgb565 */
star.color = logT2rgb565( sp->val[SPECK_TLOG] );
}
star.num = (int) sp->val[SPECK_ID];
starswap(&star);
wrote = fwrite(&star, sizeof(star), 1, outf);
} else if(as_speck) {
wrote = fprintf(outf, "%g %g %g %g %g %g\n",
p.x[0],p.x[1],p.x[2],
specklum(sp), sp->val[SPECK_TLOG], sp->val[SPECK_ID]);
} else {
double m = sp->val[SPECK_MASS];
sx += p.x[0]*m;
sy += p.x[1]*m;
sz += p.x[2]*m;
smass += m;
if(pmin.x[0] > p.x[0]) pmin.x[0] = p.x[0];
if(pmin.x[1] > p.x[1]) pmin.x[1] = p.x[1];
if(pmin.x[2] > p.x[2]) pmin.x[2] = p.x[2];
if(pmax.x[0] < p.x[0]) pmax.x[0] = p.x[0];
if(pmax.x[1] < p.x[1]) pmax.x[1] = p.x[1];
if(pmax.x[2] < p.x[2]) pmax.x[2] = p.x[2];
if(wrote < 0) /* SIGPIPE? Anyway, quit writing. */
break;
}
if(!as_sdb && !as_speck) {
report( outf, &st->dyn, st );
}
if(curstate.verbose) {
char *cp = strchr(req, '\n');
if(cp) *cp = '\0';
fprintf(stdout, "REQ: %s\n", req);
report( stdout, &st->dyn, st );
fflush(stdout);
return nspecks;
}
int serverlisten( int port ) {
struct sockaddr_in asin;
static int one = 1;
int lsock;
memset(&asin, 0, sizeof(asin));
asin.sin_family = AF_INET;
asin.sin_port = htons(port);
asin.sin_addr.s_addr = INADDR_ANY;
lsock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if(lsock < 0) {
perror("socket");
return -1;
}
setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
if(bind(lsock, (struct sockaddr *)&asin, sizeof(asin)) < 0) {
perror("bind");
return -1;
}
if(listen(lsock, 90) < 0) {
perror("listen");
return -1;
}
return lsock;
}
void serverloop( int lsock ) {
for(;;) {
struct sockaddr_in from;
FILE *inf, *outf;
char req[1280];
#if sgi
int fromlen = sizeof(from);
#else
int s = accept(lsock, (struct sockaddr *)&from, &fromlen);
if(s < 0) {
if(errno == EINTR)
continue;
perror("accept");
return;
}
inf = fdopen(s, "r");
if(fgets(req, sizeof(req), inf) == NULL) {
perror("fgets");
} else {
outf = fdopen(s, "w");
do {
serveonce( req, outf );
fflush(outf);
} while(fgets(req, sizeof(req), inf) != NULL);
fclose(outf);
}
fclose(inf);
close(s);
}
}
main(int argc, char *argv[])
{
static struct stuff tst;
curstate.st = &tst;
int c;
char opt[8];
progname = argv[0];
curstate.colorscale = -1;
curstate.has_T0 = 0;
curstate.port = 3400;
while((c = getopt(argc, argv, "T:r:t:y:g:m:c:o:p:v:iP")) != EOF) {
opt[0] = c;
opt[1] = '\0';
if(c == 'y') strcpy(opt, "type");
scanopt( opt, optarg );
}
if(optind != argc-1) {
fprintf(stderr, "Usage: %s [options] file.kira\n\
Options:\n\
-t time\n\
-r <axis><degreespertime>[@time0] Timed rotation about axis 'x'/'y'/'z'\n\
-T 16-numbers outcoords = kira * rotation(time) * tfm\n\
-y sdbtype\n\
-g group\n\
-m mag0 sdb mag = mag0 - log(lum)/(log(100)/5)\n\
-M masslum if nonzero, ignore bogus lum; use mass**3 * masslum instead.\n\
-c colorscale sdb color = log10(T)*colorscale; -c -1 => RGB565 (default)\n\
-o treestyle(1 vs 2) (default -o 2 for create_interpolated_tree2)\n\
-p portno listen for HTTP connections on that TCP port\n\
-v verbose(0 vs 1) server logs requests to its own stdout\n\
-i read from stdin, write to stdout (else be a network server)\n\
-P call preload_pdyn()\n\
", progname);
exit(1);
}
/* Ignore SIGPIPE signals -- don't crash if a caller disconnects. */
signal(SIGPIPE, SIG_IGN);
if(curstate.use_stdin) {
msg("Reading %s", argv[optind]);
kira_open( &curstate.st->dyn, curstate.st, argv[optind], curstate.verbose ? KIRA_VERBOSE : 0 );
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
int eofs = 0;
char req[512];
fprintf(stderr, "Type ? for help\n");
for(;;) {
fprintf(stderr, "\n>> ");
if(fgets(req, sizeof(req), stdin) == NULL) {
if(++eofs >= 3) break; /* quit if 3 successive EOFs */
continue;
} else {
eofs = 0;
}
if(req[0] == 'q')
break;
if(req[0] == '?' || req[0] == 'h') {
printf("Usage: each line of input yields one starlab lookup,\n\
after applying all options given on that line. Unchanged settings persist.\n\
Options take the form <keyletter>=<value> and may be separated by \"&\" or \";\"\n\
t=<time> simulation time\n\
o=<treestyle> o=1 => create_interpolated_tree, o=2 => ...tree2. Default o=2.\n\
T=<16-numbers> apply 4x4 transformation\n\
speck dump ASCII specks (default just summary information)\n\
q quit\n\
");
} else {
serveonce( req, stdout );
}
}
exit(1);
} else {
/* be a network server */
msg("Listening on port %d", curstate.port);
int lsock = serverlisten( curstate.port );
if(lsock < 0)
exit(1);
msg("Reading %s", argv[optind]);
kira_open( &curstate.st->dyn, curstate.st, argv[optind], curstate.verbose ? KIRA_VERBOSE : 0 );
msg("Ready.");
serverloop( lsock );
}