Newer
Older
curstate.use_stdin = 1;
return 1;
case 'n':
curstate.idbase = atoi(arg);
return 1;
case 'P':
curstate.preload = 1;
return 1;
case 'y':
curstate.type = atoi(arg);
return 1;
default:
msg("unknown option %c %s", opt[0], arg);
return 0;
}
}
#if !WORDS_BIGENDIAN
void starswap(db_star *st) {
int i, *wp;
static int one = 1;
/* byte-swap x,y,z, dx,dy,dz, magnitude,radius,opacity fields (32-bit float),
* 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;
} defaultTmap[] = {
// 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,
};
struct logTmap *myTmap = defaultTmap;
int nmyTmap = COUNT(defaultTmap);
static unsigned short logT2rgb565(float logT) {
int i;
for(i = 0; i < nmyTmap-1 && logT > myTmap[i].logT; i++)
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
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
return myTmap[i].rgb565;
}
int readTmap( char *fname ) {
FILE *inf;
char line[80];
#define MAXTMAP 300
struct logTmap tm[MAXTMAP];
int ntmap;
char *cp;
for(cp = fname; *cp; cp++) {
if(*cp == '&' || isspace(*cp)) {
*cp = '\0';
break;
}
}
inf = fopen(fname, "r");
if(inf == NULL) {
fprintf(stderr, "Can't open temp-to-rgb565-color map %s\n", fname);
return 0;
}
ntmap = 0;
while(fgets(line, sizeof(line), inf) != NULL) {
static char delim[] = " \t\r\n";
cp = line;
while(isspace(*cp)) cp++;
if(*cp == '\0' || *cp == '#') continue;
if(ntmap >= MAXTMAP) {
fprintf(stderr,
"%s: only room for %d temp-to-rgb565-color entries, raise MAXTMAP\n",
fname);
goto fail;
}
if(sscanf(cp, "%f 0x%x", &tm[ntmap].logT, &tm[ntmap].rgb565) < 2
&& sscanf(cp, "%f %x", &tm[ntmap].logT, &tm[ntmap].rgb565) < 2) {
fprintf(stderr, "%s: expected <logT> 0x<hex-rgb565-color> not %s",
fname, line);
goto fail;
}
ntmap++;
}
if(ntmap > 0) {
nmyTmap = ntmap;
myTmap = NewN( struct logTmap, ntmap );
memcpy( myTmap, tm, ntmap*sizeof(struct logTmap) );
}
fclose(inf);
return 1;
fail:
fclose(inf);
return 0;
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(curstate.idbase != 0)
fprintf(outf, "idbase %d\n", curstate.idbase);
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
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, ";&");
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
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] + curstate.idbase;
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] + curstate.idbase);
} 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:in:PC:")) != 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\
-n numbase add numbase to particle ids\n\
-P call preload_pdyn()\n\
-C mapfile use that colormap; each line has: log-temperature rgb565-color\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 );
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
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 );
}