Newer
Older
static char copyright[] = "Copyright (c) 2002 NCSA, University of Illinois Urbana-Champaign";
/*
* Brains of partiview: carrying and displaying data, parsing commands.
* 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.
* Revision 1.89 2002/07/10 22:51:59 slevy
* Allow ``only= field > value'' etc.
*
* Revision 1.88 2002/06/18 21:43:52 slevy
* Report copyright when "version" requested.
*
* Revision 1.87 2002/06/18 21:24:36 slevy
* Add copyright string.
* Add Illinois-open-source-license reference to LICENSE.partiview file.
*
* Revision 1.86 2002/06/05 01:13:31 slevy
* Ha -- when reading tfm's, remember to initialize has_scl!
*
* Revision 1.85 2002/06/04 23:06:07 slevy
* Use parti_idof(), not parti_object( NULL, &st, 0 ), to turn object into id.
*
* Revision 1.84 2002/04/22 17:58:49 slevy
* Allow "w" option to "bound" command: compute bounding box in world
* instead of object coordinates.
*
* Revision 1.83 2002/04/17 20:47:58 slevy
* Add a not-quite-proprietary notice to all source files.
* Once we pick a license this might change, but
* in the mean time, at least the NCSA UIUC origin is noted.
*
* Revision 1.82 2002/04/16 18:40:26 slevy
* Move tokenize() and rejoinargs() into findfile.c,
* and out of this overstuffed piece of junk.
*
* Revision 1.81 2002/04/12 05:50:20 slevy
* Fix (?) "only=" etc. commands, broken since I added the selection stuff last July!
*
* Revision 1.80 2002/03/31 22:40:32 slevy
* "tfm" command -- only print full matrices if "tfm -v" given,
* otherwise just x y z rx ry rz scale; print matrices in %g format for
* full precision; accept 7th parameter as scale factor on input
* just as we print it on output.
*
* Revision 1.79 2002/03/14 18:14:58 slevy
* Peel out a bit more CAVE code,
* and refer specifically to Marcus Thiebaux's virdir
* since there's now also a Matt Hall version.
*
* Revision 1.78 2002/03/14 04:54:09 slevy
* Strip out a bunch of virdir-specific CAVE menu clutter,
* now moved into partimenu.c.
*
* Revision 1.77 2002/03/11 22:31:23 slevy
* Move virdir-specific parti_seto2w() and specks_display() to partiview.cc.
* "rawdata -a" particle-dump includes position, color, brightness too.
*
* Revision 1.76 2002/02/02 04:13:07 slevy
* Unless PARTIMENU explicitly set, just get rid of the blasted menus.
*
* Revision 1.75 2002/01/27 00:38:19 slevy
* Add "setenv name value" data command.
*
* Revision 1.74 2002/01/23 03:56:34 slevy
* Add "timealign", "skipblanktimes" commands.
* Default change: no longer skip blank times!
* Per-data time ranges now extend overall clock range,
* don't replace it.
* Reset material properties (shininess, specular, ambient)
* when drawing a lighted mesh.
*
* Revision 1.73 2001/12/28 07:23:57 slevy
* Move plugins (kira, warp, ieeeio) off to separate source files.
* "where" command gives full-precision values, and reports jump-pos with scale.
* Allow for model-specific render function (initially for Maya models).
* env TXDEBUG.
*
* Revision 1.72 2001/11/09 05:27:53 slevy
* In specks_set_timestep(), don't set clock's range if we only have
* a single timestep ourselves!
*
* Revision 1.71 2001/11/08 06:32:52 slevy
* Extract async code into async.c.
* Add pointsize metering, normally #ifdef USE_PTRACK'ed out.
*
* Revision 1.70 2001/11/06 06:20:30 slevy
* Centralize test for nonempty timestep slot: specks_nonempty_timestep().
* Fix tokenize() for case of "quoted" or 'quoted' arg strings.
*
* Revision 1.69 2001/10/19 17:48:51 slevy
* Don't leak FILE in specks_read_waveobj().
*
* Revision 1.68 2001/08/29 17:54:00 slevy
* Make rejoinargs() work robustly -- use a private static malloced area,
* don't overwrite args in memory.
*
* Revision 1.67 2001/08/28 18:27:34 slevy
* Remove lots of unused variables. Move some used only in CAVE code
* inside #ifdef brackets.
*
* Revision 1.66 2001/08/28 02:05:22 slevy
* Fix format string usage.
*
* Revision 1.65 2001/08/26 17:40:04 slevy
* Bounds-check all references to st->meshes[][], st->annot[][], etc. --
* all those maintained by specks_timespecksptr. We no longer guarantee
* that st->curtime is always in range 0..st->ntimes-1, so just yield NULL
* for out-of-range references. New CURDATATIME(fieldname) does it.
*
* Revision 1.64 2001/08/26 02:10:40 slevy
* "color rgb ..." sets colors of otherwise-uncolored mesh objects.
* Only call parti_parse_args() if non-CAVE.
*
* Revision 1.63 2001/08/24 01:02:38 slevy
* Add polygonal meshes -- wavefront .obj models.
*
* Revision 1.62 2001/08/16 19:58:56 slevy
* Pull non-specks-specific code out of partibrains.c
* and into partiview.cc, using new parti_add_commands hook.
*
* Revision 1.61 2001/08/16 17:23:41 slevy
* New parti_parse_args() for generic add-on commands.
* "where" prints more information.
*
* Revision 1.60 2001/07/19 20:10:23 slevy
* st->threshsel is now kept as a SEL_DEST.
* Fix seldest2src(), not even wrong.
* Use specks_reupdate() after changing thresh, so the reported
* selcount should be right.
* specks_rethresh(): keep track of whether anything changed,
* and increment st->selseq if so.
*
* Revision 1.59 2001/07/18 19:24:57 slevy
* parse_selexpr() returns bit-encoded value saying whether src or dest or
* both were filled in.
*
* Revision 1.58 2001/07/17 17:28:08 slevy
* Increase MAXPTSIZE to allow bigger dots!
*
* Revision 1.57 2001/07/16 17:58:37 slevy
* Don't take spurious snapshot if "snapset" command gets -... args.
* Revert to compatible texture behavior: texture -A is again the default,
* use texture -O for "over"-style blending.
*
* Revision 1.56 2001/07/15 23:09:46 slevy
* Um, let "wanted == 0" and SEL_USE indicate that we want to match all pcles.
*
* Revision 1.55 2001/07/15 22:55:14 slevy
* Er, those 'leadc' parameters to seldest()/selsrc() are ints, not SelTokens.
*
* Revision 1.54 2001/07/12 21:42:25 slevy
* Use new selcounts() function to report stats whenever we mention a SelOp.
* ``sel <src>'' alone now works too, to just report match count.
*
* Revision 1.53 2001/07/10 17:18:05 slevy
* threshsel is a src, not a dest-type SelOp.
*
* Revision 1.52 2001/07/09 23:46:56 slevy
* A bit more ripening of selection system...
* And, report match counts from "sel", "thresh", "emph".
*
* Revision 1.51 2001/07/07 15:35:49 slevy
* Implement more (most?) of selection framework:
* selsrc(), seldest(), selname(), seltoken().
* "thresh" now accepts "-s 'destexpr'".
* Add new selthresh SelOp.
*
* Revision 1.50 2001/07/04 03:44:12 slevy
* Add framework of set-selection stuff; not really usable yet.
* Next: implement "see" in drawspecks().
* Add "picked" callback which gets notified of all pick results.
*
* Revision 1.49 2001/06/30 18:14:22 slevy
* Provide for storing another bit in rgba alpha field: EMPHBIT, for
* emphasis tag.
* Use new sfStrDrawTJ (with transform & justification) for text.
* Yeow, handle polymax properly -- default == infinity!
* Add "vcmap" for per-datafield colormaps.
* Enable GL_SMOOTH mode to get texture colors to work right (huh? why do we need to?).
* "tfm c"/"tfm w" choose cam vs. world (default) location for object tfms.
*
* Revision 1.48 2001/05/30 14:32:55 slevy
* Add subcameras ("subcam" command).
* popen() needs "r" not "rb" -- no such thing as binary mode.
* kira_open() gets original filename if we can't find it, for error messaging.
*
* Revision 1.47 2001/05/15 12:18:57 slevy
* New interface to dynamic-data routines.
* Now, the only #ifdef KIRA/WARP needed in partibrains.c are
* the data-command initialization routines. All others,
* including control-command parsing and specialized drawing,
* is now via a function table.
*
* Revision 1.46 2001/05/14 15:51:34 slevy
* Initialize new speckseq value whenever we make a new specklist.
* Put colorseq/sizeseq/threshseq invalidation in kira_parti, not here,
* since we needn't do it when warping.
* By default, clock range is whatever it had been set to before.
*
* Revision 1.45 2001/05/12 07:22:24 slevy
* Add get-time-range func for dynamic data.
* Initialize all dynamic-data stuff explicitly.
*
* Revision 1.44 2001/05/11 10:05:38 slevy
* Add "warp" command if -DUSE_WARP.
* Ellipsoids allow 3-component (Rx Ry Rz) orientation numbers too.
* st->dyndata doesn't mean we should trash the anima[][] specklist.
* Need to keep it intact for warping.
*
* Revision 1.43 2001/05/02 09:51:01 slevy
* Add "ellipsoids" and "meshes" commands to toggle their display.
* Finally parse snapshot arguments properly...?
*
* Revision 1.42 2001/04/26 08:52:46 slevy
* Add hook for off-screen rendering: "-w width[xheight]" option for
* snapshot/snapset. Not actually implemented yet.
* Add "clipbox hide". This (a) doesn't display the big yellow box
* and (b) doesn't enable OpenGL clipping -- just whatever object culling
* the draw routine does anyway.
* specks_draw_mesh() now pays attention to drawing style (solid/line/plane/point).
* When drawing ellipsoids, disable blending altogether if bgcolor != 0.
* Small, distant labels now disappear by default. To get the old
* draw-tiny-line behavior, use a negative "labelmin" value.
*
* Revision 1.41 2001/04/20 13:47:39 slevy
* Allow *cment commands to alter multiple colormap entries: new editcmap().
*
* Revision 1.40 2001/04/10 19:18:33 slevy
* Open sdb files (and while we're at it, other files too) in binary mode.
*
* Revision 1.39 2001/04/04 20:33:02 slevy
* Use findfile() for "read" ctrl-command.
*
* Revision 1.38 2001/03/30 16:49:00 slevy
* Change enum SurfStyle to avoid mentioning POINT, which Windows uses too.
*
* Revision 1.37 2001/03/30 14:00:42 slevy
* Allow cment/boxcment/textcment as data commands too.
* Add "ghosts" ctl command (not really implemented).
* Add "winsize" ctl command.
* Ellipsoids now accept -l levelno option, in which case
* "hide levelno"/"show levelno" applies to them. Default is -1,
* which means "show if any level is shown", but hidden by "hide all".
* Scrap ghost maintenance. Do that elsewhere instead.
* Make "maxcomment" work properly.
*
* Revision 1.36 2001/03/19 11:55:08 slevy
* New version.c (derived from ../VERSION) contains current version string.
* New "version" command in partibrains reports that and the partibrains.c CVS ver no.
*
* Revision 1.35 2001/03/19 10:39:07 slevy
* Handle speck comments properly.
*
* Revision 1.34 2001/03/15 18:19:06 slevy
* Don't include comments in argc/argv -- it complicates things.
* Have a separate "comment" pointer. Pass it to specks_read_ellipsoid too.
*
* Revision 1.33 2001/03/15 15:37:06 slevy
* Yeow -- handle VIRDIR prefix properly!
* Complain of unrecognized data commands.
*
* Revision 1.32 2001/03/14 17:27:05 slevy
* Make rejoinargs() work -- don't omit last arg.
* "object" command alone reports our currently selected object.
*
* Revision 1.31 2001/03/13 22:45:08 slevy
* Add "verbose" flag to parti_allobjs, so "gall -v ..."
* reports object name before invoking each command.
*
* Revision 1.30 2001/03/13 08:23:39 slevy
* Use parti_object's new "create-if-not-present" flag.
* Data-language references can create, command-language ones can't.
* Switch specks_read() to argc/argv style, using new "tokenize()" function.
* Some commands still want the original string, so we also have rejoinargs().
* Allow for adjustable comment length with "maxcomment" data command.
* New "ellipsoid" and "mesh" objects. Only quadmeshes implemented right now.
* Data-language "tfm" command is now quiet. Command-language tfm still verbose.
* Check at run time for endian-config errors and refuse to run if wrong!
*
* Revision 1.29 2001/03/08 22:02:29 slevy
* Disable the parti menu unless PARTIMENU envar set.
* Allow alpha to adjust brightness of mesh objects.
*
* Revision 1.28 2001/03/05 03:04:41 slevy
* Add mesh objects. Or, quad meshes, anyway.
*
* Revision 1.27 2001/03/04 16:47:35 slevy
* Make "add" and "eval" behave consistently.
* polyorivar and texturevar now accept field names as well as numbers.
*
* Revision 1.25 2001/02/19 22:01:16 slevy
* Satisfy windows C compiler: pull enum FadeModel outside struct speck, etc.
*
* Revision 1.24 2001/02/19 20:50:33 slevy
* Oops, "object" should always invoke parti_object() whether there's an
* alias or not!
*
* Revision 1.23 2001/02/17 22:02:54 slevy
* Enlarge polygons so that unit circle is inscribed, not circumscribed.
* Then "txscale .5" always shows entire texture regardless of polysides.
* Add new "ptsize" command -- makes more sense than "fast". "fast" still works.
*
* Revision 1.22 2001/02/17 17:44:05 slevy
* For polygons, rotate circle of vertices by 1/2 step.
* Then, for "polysides 4" and "txscale .707",
* the vertices coincide with the corners of the 0..1 texture.
*
* Revision 1.21 2001/02/17 05:39:45 slevy
* Allow (in data language) "object gN=NAME".
*
* Revision 1.20 2001/02/15 05:41:12 slevy
* new textcmap, textcment commands. Regularize color-gamma-mapping.
* Object aliases: "object gN=ALIAS", or in command mode, "gN=ALIAS".
* Accept "ellipsoid" data tag; not yet implemented.
*
* Revision 1.19 2001/02/05 00:41:52 slevy
* Accept "time" as synonym for "step".
* Add "pickrange".
* Mention jump, center in help msg.
* Revision 1.17 2001/02/03 16:49:42 slevy
* Update cookedcmap when "cment" changes cmap.
*
* Revision 1.15 2001/02/03 14:50:44 slevy
* Add "setgamma" (abbr. "setgam" or "cgam") command to adjust colors.
* Add "kira tree {off|on|cross|tick} [tickscale]" subcommand
* for showing tree structure of interacting groups.
*
* Revision 1.14 2001/01/31 17:11:54 slevy
* Ensure that, for starlab, clock is always in "continuous" mode.
*
* Revision 1.13 2001/01/31 17:07:12 slevy
* Add RCS Id and Log strings.
*
*/
#define __USE_MISC /* makes <math.h> define sqrtf() on GNU libc */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#if !sgi && !defined(sqrtf)
# define sqrtf(x) sqrt(x) /* if no sqrtf() */
#endif
#undef isspace /* hack for irix 6.5 back-compat */
#undef isdigit
#undef isalnum
#if unix
# include <unistd.h>
# include <sys/types.h>
# include <netinet/in.h> /* for htonl */
# ifndef WORDS_BIGENDIAN
# include "config.h" /* for WORDS_BIGENDIAN */
# endif
#define RGBALPHA(rgb, alpha) ((rgb) | (alpha))
#define RGBWHITE 0xFFFFFF00
#define PACKRGBA(r,g,b,a) ((r)<<24 | (g)<<16 | (b)<<8 | (a))
#define RGBA_R(rgba) (((rgba)>>24) & 0xFF)
#define RGBA_G(rgba) (((rgba)>>16) & 0xFF)
#define RGBA_B(rgba) (((rgba)>>8) & 0xFF)
#define RGBA_A(rgba) (((rgba)) & 0xFF)
#else
#define RGBALPHA(rgb, alpha) ((rgb) | ((alpha)<<24))
#define RGBWHITE 0x00FFFFFF
#define PACKRGBA(r,g,b,a) ((a)<<24 | (b)<<16 | (g)<<8 | (r))
#define RGBA_R(rgba) (((rgba)) & 0xFF)
#define RGBA_G(rgba) (((rgba)>>8) & 0xFF)
#define RGBA_B(rgba) (((rgba)>>16) & 0xFF)
#define RGBA_A(rgba) (((rgba)>>24) & 0xFF)
#define THRESHBIT PACKRGBA(0,0,0,1)
#define EMPHBIT PACKRGBA(0,0,0,2)
#define EXTRABITS PACKRGBA(0,0,0,0xff)
#define RGBBITS PACKRGBA(0xff,0xff,0xff,0)
#include "geometry.h"
#include <GL/gl.h>
#include "shmem.h" /* NewN(), etc. */
#include "futil.h"
#include "specks.h"
#include "textures.h"
#include "findfile.h"
#include "partiviewc.h"
#include "sfont.h"
#include <sys/types.h>
#include <signal.h>
#ifdef sgi
#include <malloc.h> /* for mallinfo(), amallinfo() */
#endif
#if CAVEMENU
# include "cavemenu.h"
# include "partimenu.h"
# define IFCAVEMENU(x) (x)
#else
# define IFCAVEMENU(x) /* nothing */
#endif
#if THIEBAUX_VIRDIR
# include "vd_util.h"
#endif
/* Star Renderer (.sdb) structure -- from stardef.h */
typedef enum {ST_POINT, ST_BRIGHT_CLOUD ,ST_DARK_CLOUD, ST_BOTH_CLOUD, ST_OFF} stype;
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
typedef struct {
float x, y, z;
float dx, dy, dz;
float magnitude, radius;
float opacity;
int num;
unsigned short color;
unsigned char group;
unsigned char type;
} db_star;
typedef struct hrec { float t; int num;} hrec_t;
typedef struct mrec { float mass, x, y, z, vx, vy, vz, rho, temp, sfr, gasmass;
int id, token;} mrec_t;
/* end Star Renderer */
#define VDOT( v1, v2 ) ( (v1)->x[0]*(v2)->x[0] + (v1)->x[1]*(v2)->x[1] + (v1)->x[2]*(v2)->x[2] )
static int defcmap[] = {
0x11eeee00,
0x1106ee00, 0x120ea900, 0x1316ce00, 0x1520d500, 0x172ece00, 0x193fcb00,
0x1c54b400, 0x206da400, 0x24889200, 0x2aa58400, 0x33c07600, 0x3ed96a00,
0x4eed6100, 0x63fa5a00, 0x7efe5100, 0x99fb4c00, 0xafef4700, 0xc0dc4000,
0xcbc33900, 0xd4a83000, 0xda8b2900, 0xdf702700, 0xe2572500, 0xe5411700,
0xe82f1000, 0xea211500, 0xeb171400, 0xed0f1200, 0xee0aee00,
0xffffff00,
};
int orientboxcolor = PACKRGBA( 0xff, 0xff, 0, 0xff );
void specks_read( struct stuff **stp, char *fname );
void specks_read_boxes( struct stuff *st, char *fname, int timestep );
int specks_add_box( struct stuff *st, struct AMRbox *box, int timestep );
int specks_purge( void *vstuff, int nbytes, void *aarena );
int specks_count( struct specklist *head );
int specks_gobox( struct stuff *st, int boxno, int argcrest, char *argvrest[] );
int specks_cookcment( struct stuff *st, int cment );
void specks_rgbremap( struct stuff *st );
struct specklist **specks_find_annotation( struct stuff *, struct specklist **);
void specks_set_current_annotation( struct stuff *st, char *annotation );
void specks_add_annotation( struct stuff *st, char *annotation, int timestep );
extern int getfloats( float *v, int nfloats, int arg0, int argc, char **argv );
extern int specks_set_byvariable( struct stuff *st, char *str, int *val );
void strncpyt( char *dst, char *src, int dstsize ) {
int len = strlen(src);
if(len >= dstsize) len = dstsize-1;
memcpy(dst, src, len);
dst[len] = '\0';
}
#ifdef sgi
static float defgamma = 1.0;
#else
static float defgamma = 2.5;
#endif
struct stuff *
specks_init( int argc, char *argv[] )
{
int i;
struct stuff *st = NewN( struct stuff, 1 );
i = PACKRGBA(1, 0, 0, 0);
if(*(char *)&i != 1) {
msg("specks_init(): trouble: is WORDS_BIGENDIAN mis-set? Giving up.");
exit(1);
}
memset(st, 0, sizeof(*st));
st->spacescale = 1.0;
st->fog = 0;
st->psize = 1;
st->alpha = .5;
st->gamma = defgamma;
st->rgbgamma[0] = st->rgbgamma[1] = st->rgbgamma[2] = 1.0;
st->rgbright[0] = st->rgbright[1] = st->rgbright[2] = 1.0;
specks_rgbremap( st );
st->alias = NULL;
st->useme = 1;
st->usepoly = 0;
st->usepoint = 1;
st->usetext = 1;
st->usetextaxes = 1;
st->usetextures = 1;
st->useboxes = 1;
st->staticmeshes = NULL;
st->mullions = 0;
st->polysizevar = -1;
st->polyarea = 0;
st->polyorivar0 = -1;
st->texturevar = -1;
st->txscale = .5;
st->boxlabels = 0;
st->boxlabelscale = 1.0;
st->boxlevelmask = ~0; /* all levels on */
st->boxaxes = 0; /* boxes don't show orientation markers */
st->goboxscale = 1.0;
st->textsize = .05;
st->npolygon = 11;
st->subsample = 1;
st->maxcomment = sizeof(st->sl->specks->title) - 1;
st->dyn.enabled = 0;
st->dyn.data = NULL;
st->dyn.getspecks = NULL;
st->dyn.draw = NULL;
st->dyn.trange = NULL;
st->dyn.help = NULL;
st->dyn.ctlcmd = NULL;
st->dyn.free = NULL;
st->speckseq = 0;
st->menudemandfps = 4.0;
st->pfaint = .05; /* params for "fast" point-drawing */
st->plarge = 10;
st->polymin = .5; /* don't draw polygons if smaller (pixels) */
st->polymax = 1e8; /* don't allow polygons to get bigger than this (pixels) */
st->polyfademax = 0;
st->textmin = 2; /* replace labels with line-segments if smaller (pixels) */
st->ntextures = 0;
st->textures = NULL;
st->fade = F_SPHERICAL;
st->fadeknee1 = 10.0;
st->fadeknee2 = 1.0;
st->knee2steep = 1.0;
st->gscale = 1.;
st->gtrans.x[0] = st->gtrans.x[1] = st->gtrans.x[2] = 0;
st->objTo2w = Tidentity;
st->ncmap = st->boxncmap = st->textncmap = COUNT(defcmap);
st->cmap = NewN(struct cment, COUNT(defcmap));
st->boxcmap = NewN(struct cment, COUNT(defcmap));
st->textcmap = NewN(struct cment, COUNT(defcmap));
st->cmap[i].raw = st->boxcmap[i].raw = st->textcmap[i].raw
= htonl(defcmap[i]);
st->cmap[i].cooked = st->boxcmap[i].cooked = st->textcmap[i].cooked
= specks_cookcment( st, st->cmap[i].raw );
/* Ensure that textcmap[0] is white by default */
st->textcmap[0].raw = PACKRGBA( 170, 170, 170, 0 );
st->textcmap[0].cooked = specks_cookcment( st, st->textcmap[0].raw );
st->sizedby = 0;
st->coloredby = 1;
st->sizeseq = st->colorseq = st->threshseq = 0;
st->trueradius = 0;
st->sdbvars = shmstrdup( "mcr" );
st->useemph = 0;
selinit( &st->emphsel );
st->emphfactor = 10;
selinit( &st->threshsel );
selinit( &st->seesel );
st->ntimes = 0;
st->ndata = 0;
st->curtime = 0;
st->curdata = 0;
st->datatime = 0;
st->usertrange = 0;
st->utmin = -HUGE;
st->utmax = HUGE;
st->utwrap = 0.1;
st->sl = NULL;
st->boxes = NULL;
st->boxlevels = 0;
st->boxlinewidth = 0.75;
st->clk = NewN(SClock, 1);
clock_init(st->clk);
clock_set_running(st->clk, 1);
memset(st->anima, 0, sizeof(st->anima));
memset(st->annot, 0, sizeof(st->annot));
memset(st->datafile, 0, sizeof(st->datafile));
memset(st->fname, 0, sizeof(st->fname));
memset(st->meshes, 0, sizeof(st->meshes));
#if CAVE
shmrecycler( specks_purge, st );
#endif
for(i = 1; i < argc; i++)
specks_read( &st, argv[i] );
IFCAVEMENU( partimenu_init( st ) );
return st;
}
void specks_rethresh( struct stuff *st, struct specklist *sl, int by )
{
int i;
int curdata = st->curdata;
int nel = sl->nspecks;
float threshmin = st->thresh[0], threshmax = st->thresh[1];
struct speck *p = sl->specks;
SelMask *sel = sl->sel;
sl->threshseq = st->threshseq;
if(sl->text != NULL) /* specklists with labels shouldn't be thresholded */
return;
if(curdata >= st->ndata)
curdata = 0;
min = (SMALLSPECKSIZE(by)>=sl->bytesperspeck) ? 0 : st->usethresh&P_THRESHMIN;
max = (SMALLSPECKSIZE(by)>=sl->bytesperspeck) ? 0 : st->usethresh&P_THRESHMAX;
threshseldest = st->threshsel;
for(i = 0, p = sl->specks; i < nel; i++, p = NextSpeck( p, sl, 1 )) {
if((min&&p->val[by]<threshmin) || (max&&p->val[by]>threshmax)) {
/* p->rgba |= THRESHBIT; */
/* p->rgba &= ~THRESHBIT; */
changed |= was ^ sel[i];
}
if(changed) {
sl->selseq++;
if(st->selseq < sl->selseq) st->selseq = sl->selseq;
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
int specks_cookcment( struct stuff *st, int cment )
{
unsigned char crgba[4];
memcpy(crgba, &cment, 4); /* XXX 64-bit bug? */
return (cment & ~RGBWHITE) |
PACKRGBA(
st->rgbmap[0][crgba[0]],
st->rgbmap[1][crgba[1]],
st->rgbmap[2][crgba[2]],
0 );
}
void specks_rgbremap( struct stuff *st )
{
int i, k;
for(i = 0; i < 256; i++) {
float t = (float)i / 256;
float v = 255.99f * pow(t, 1/st->rgbgamma[0]);
k = (int) (st->rgbright[0] * v);
st->rgbmap[0][i] = (k <= 0) ? 0 : (k > 255) ? 255 : k;
if(st->rgbgamma[0] != st->rgbgamma[1])
v = 255.99f * pow(t, 1/st->rgbgamma[1]);
k = (int) (st->rgbright[1] * v);
st->rgbmap[1][i] = (k <= 0) ? 0 : (k > 255) ? 255 : k;
if(st->rgbgamma[1] != st->rgbgamma[2])
v = 255.99f * pow(t, 1/st->rgbgamma[2]);
k = (int) (st->rgbright[2] * v);
st->rgbmap[2][i] = (k <= 0) ? 0 : (k > 255) ? 255 : k;
}
/* remake colormap too */
for(i = 0; i < st->ncmap; i++)
st->cmap[i].cooked = specks_cookcment( st, st->cmap[i].raw );
void specks_recolor( struct stuff *st, struct specklist *sl, int by )
{
struct valdesc *vd;
int i;
int curdata = st->curdata;
int nel = sl->nspecks;
struct speck *sp = sl->specks;
float cmin, cmax, normal;
int ncmap = st->ncmap;
struct cment *cmap = st->cmap;
sl->coloredby = by;
sl->colorseq = st->colorseq;
if(sl->text != NULL) /* specklists with labels shouldn't be recolored */
return;
if(curdata >= st->ndata)
curdata = 0;
if(by == CONSTVAL) {
/* Hack -- color by given RGB value */
char crgba[4];
r = (vd->cmin<=0) ? 0 : vd->cmin>=1 ? 255 : (int)(255.99f * vd->cmin);
g = (vd->cmax<=0) ? 0 : vd->cmax>=1 ? 255 : (int)(255.99f * vd->cmax);
b = (vd->mean<=0) ? 0 : vd->mean>=1 ? 255 : (int)(255.99f * vd->mean);
crgba[0] = st->rgbmap[0][r];
crgba[1] = st->rgbmap[0][g];
crgba[2] = st->rgbmap[0][b];
sp->rgba = rgba | (sp->rgba & EXTRABITS);
}
return;
}
if(by >= MAXVAL || by < 0 || SMALLSPECKSIZE(by) > sl->bytesperspeck)
by = 0;
vd = &st->vdesc[curdata][by];
if(vd->vncmap > 0) {
ncmap = vd->vncmap;
cmap = vd->vcmap;
}
cmin = vd->cmin, cmax = vd->cmax;
if(cmin == cmax && cmin == 0 || (vd->call && !vd->cexact)) {
vd->cmin = cmin = vd->min;
vd->cmax = cmax = vd->max;
}
normal = (cmax != cmin && ncmap>2) ? (ncmap-2)/(cmax - cmin) : 0;
rgb565 = !strcmp(vd->name, "rgb565") || !strcmp(vd->name, "colors565");
/* cexact field means:
* 0 (default): scale data range to cmap index 1..ncmap-2;
* use 0 and ncmap-1 for low- and high- out-of-range values.
*
* 1 ("exact"): use data value as literal colormap index, 0..ncmap-1.
*/
for(i = 0; i < nel; i++, sp = NextSpeck(sp, sl, 1)) {
if(rgb565) {
index = sp->val[by];
sp->rgba = PACKRGBA(
rgbmap[0][(index&0xF800)>>(11-(8-5))],
rgbmap[1][(index&0x07E0)>>(5-(8-6))],
rgbmap[2][(index&0x1F)<<(8-5)],
0 )
| (sp->rgba & EXTRABITS);
} else {
index = vd->cexact ? sp->val[by] + cmin
: (sp->val[by] - cmin) * normal + 1;
if(index < 0) index = 0;
else if(index >= ncmap) index = ncmap-1;
sp->rgba = cmap[index].cooked | (sp->rgba & EXTRABITS);
}
}
}
void specks_resize( struct stuff *st, struct specklist *sl, int by )
{
int i;
int nel = sl->nspecks;
struct speck *sp = sl->specks;
int curdata = st->curdata;
struct valdesc *vd;
float lmin, lmax, normal;
sl->sizedby = by;
sl->sizeseq = st->sizeseq;
if(sl->text != NULL) /* specklists with labels shouldn't be resized */
return;
if(curdata < 0 || curdata >= st->ndata)
curdata = 0;
if(by == CONSTVAL) {
vd = &st->vdesc[curdata][CONSTVAL];
for(i = 0; i < nel; i++, sp = NextSpeck(sp, sl, 1)) {
if(SELECTED(sl->sel[i], &st->emphsel)) {
sp->size *= st->emphfactor;
}
}
return;
}
if(by < 0 || by >= MAXVAL)
by = 0;
vd = &st->vdesc[curdata][by];
lmin = vd->lmin, lmax = vd->lmax;
if(lmin == lmax && lmin == 0 || vd->lall) {
vd->lmin = lmin = vd->min;
vd->lmax = lmax = vd->max;
}
if(lmax == lmin)
normal = 1;
else
normal = 1 / (lmax - lmin);
if(st->useemph && st->emphsel.use != SEL_NONE) {
for(i = 0; i < nel; i++, sp = NextSpeck(sp, sl, 1)) {
sp->size = (sp->val[by] - lmin) * normal;
if(SELECTED(sl->sel[i], &st->emphsel)) {
sp->size *= st->emphfactor;
}
} else {
/* normal case */
for(i = 0; i < nel; i++, sp = NextSpeck(sp, sl, 1))
sp->size = (sp->val[by] - lmin) * normal;
}
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
}
void specks_datawait(struct stuff *st) {
#if USE_IEEEIO
while(st->fetching && st->fetchpid > 0
&& st->fetchtime == st->curtime
&& st->fetchdata == st->curdata)
usleep(50000);
#endif
}
#ifdef USE_IEEEIO
void specks_ieee_server( void *vst ) {
struct stuff *st = (struct stuff *)vst;
struct specklist *sl;
prctl(PR_TERMCHILD); /* Die when parent dies */
/* Await a request */
for(;;) {
time_t then;
while(st->fetching <= 0)
sginap(5);
then = time(NULL);
sl = specks_ieee_read_timestep( st, st->subsample,
st->fetchdata, st->fetchtime );
if(then + 5 < time(NULL))
msg("... got %x (%d particles) from %s", sl, specks_count(sl),
st->fname[st->fetchdata][st->fetchtime]);
if(st->curtime == st->fetchtime && st->curdata == st->fetchdata
&& sl != NULL) {
st->sl = sl;
parti_redraw();
}
st->fetching = 0;
}
}
#endif /*USE_IEEEIO*/
void specks_set_timebase( struct stuff *st, double timebase ) {
clock_set_timebase( st->clk, timebase );
/* parti_set_timebase( st, timebase ); */
}
/* ignore it! */
/* or maybe use fspeed to specify finite clock resolution */
{
struct specklist *sl = st->sl;
struct specklist **slp;
tmin = st->clk->tmin;
tmax = st->clk->tmax;
/*if(tmin < st->utmin)*/ tmin = st->utmin;
/*if(tmax > st->utmax)*/ tmax = st->utmax;
/* Only expand clock's existing time range */
if(tmin > st->clk->tmin) tmin = st->clk->tmin;
if(tmax < st->clk->tmax) tmax = st->clk->tmax;
clock_set_range( st->clk, tmin, tmax, st->utwrap );
if(st->dyn.enabled && st->dyn.getspecks) {
sl = (*st->dyn.getspecks)(&st->dyn, st, realtime);
if(sl == NULL)
return;
/* Do we need this? */ /* *slp = sl; */ /* Guess not... */
if(timestep < 0) timestep = 0;
slp = specks_timespecksptr( st, st->curdata, timestep );
if(*slp != NULL && (*slp)->subsampled > st->subsample) {
specks_discard( st, slp );
}
sl = *slp;
#ifdef USE_IEEEIO
if(sl == NULL && (st->fetching == 0 || st->datasync)
&& st->curdata>=0 && st->curdata<st->ndata
&& st->datafile[st->curdata] != NULL
&& timestep>=0 && timestep<st->ntimes
&& st->datafile[st->curdata][timestep] != NULL) {
st->fetchdata = st->curdata;
st->fetchtime = timestep;