Newer
Older
* 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))
#else
#define RGBALPHA(rgb, alpha) ((rgb) | ((alpha)<<24))
#define RGBWHITE 0x00FFFFFF
#define PACKRGBA(r,g,b,a) ((a)<<24 | (b)<<16 | (g)<<8 | (r))
#endif
#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)
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
#if CAVE
# define CAVEMENU 1
#endif
#include "geometry.h"
#include <GL/gl.h>
#if CAVEMENU
#include <cave_ogl.h>
#include "cavemenu.h"
#include "vd_util.h"
#define IFMENU(x) (x)
#else
#define IFMENU(x)
#endif
#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
/* Star Renderer (.sdb) structure -- from stardef.h */
typedef enum {ST_POINT, ST_BRIGHT_CLOUD ,ST_DARK_CLOUD, ST_BOTH_CLOUD, ST_OFF} stype;
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
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] )
#if CAVEMENU
int parti_menuwall, parti_menubox[4];
static MenuHead *pmenu = NULL;
static MenuHead *stubmenu = NULL;
struct ments {
MenuEnt *alpha, *point, *poly, *label, *psize, *polysize, *fog;
MenuEnt *step, *fwd, *lumvar, *slum, *colorvar, *where[4];
MenuEnt *viewall, *setscale, *speed, *fspeed, *every;
MenuEnt *seedata, *box, *boxlevel[12];
MenuEnt *annot;
MenuEnt *tknob[3];
MenuEnt *menu;
} ment;
struct boxleveler {
struct stuff *st;
int level;
};
void set_tknob( float val, MenuEnt *me, void *st );
void set_psize( float psize, MenuEnt *me, void *st );
void set_polysize( float psize, MenuEnt *me, void *st );
void set_alpha( float alpha, MenuEnt *me, void *st );
void set_point( int on, MenuEnt *me, void *st );
void set_poly( int on, MenuEnt *me, void *st );
void set_label( int on, MenuEnt *me, void *st );
void set_step( float time0, MenuEnt *me, void *st );
void set_fwd( int fwd, MenuEnt *me, void *st );
void set_slum( float slum, MenuEnt *me, void *st );
void set_lumvar( int which, MenuEnt *me, void *st );
void set_colorvar( int which, MenuEnt *me, void *st );
void set_seedata( int which, MenuEnt *me, void *st );
void set_speed( float speed, MenuEnt *me, void *st );
void set_fspeed( float fspeed, MenuEnt *me, void *st );
void set_every( float every, MenuEnt *me, void *st );
void set_scale( float logscale, MenuEnt *me, void *st );
void set_viewall( int all, MenuEnt *me, void *st );
void set_allboxes( int on, MenuEnt *me, void *st );
void set_boxlevel( int on, MenuEnt *me, void *bleveler );
void set_where( int unused, MenuEnt *me, void *st );
void set_menu( int on, MenuEnt *me, void *st );
#endif /*CAVEMENU*/
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 );
static char separ[] = " \t\n";
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 );
char *menuopt;
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] );
#if CAVEMENU
menu_preinit();
pmenu = menu_create( .05, .95 );
menu_setfont( pmenu, font_small );
ment.annot = menu_addentry( pmenu, " ", NULL, NULL );
menu_addentry( pmenu, " ", NULL, NULL );
menuopt = getenv("PARTIMENU");
if(menuopt == NULL) {
menuopt = "label";
st->hidemenu = 1;
}
if(strstr(menuopt, "survey")) { /* SC99DEMO star-formation survey */
for(i = 0; i < 3; i++) {
struct boxleveler *tb = NewN( struct boxleveler, 1 );
tb->st = st;
tb->level = i;
ment.tknob[i] = menu_addknob( pmenu, NULL, set_tknob, 0, 0,4, tb );
}
}
menu_addentry( pmenu, " ", NULL, NULL );
ment.psize = menu_addknob( pmenu, NULL, set_psize, st->psize, 0.1,20, st );
ment.slum = menu_addknob( pmenu, NULL, set_slum,
st->vdesc[st->curdata][st->sizedby].lum, .1, 10, st );
ment.lumvar = menu_addtoggle( pmenu, NULL, set_lumvar, st->sizedby, MAXVAL, st );
ment.colorvar = menu_addtoggle( pmenu, NULL, set_colorvar, st->coloredby, MAXVAL, st );
ment.seedata = menu_addtoggle( pmenu, NULL, set_seedata, st->curdata, 2, st );
if(strstr(menuopt, "label"))
ment.label = menu_addtoggle( pmenu, NULL, set_label, st->usetext, 2, st );
if(strstr(menuopt, "poly"))
ment.poly = menu_addtoggle( pmenu, NULL, set_poly, st->usepoly, 2, st );
menu_addentry( pmenu, " ", NULL, NULL ); /* spacer */
#ifndef STATIC_SPECKS
ment.fspeed = menu_addknob( pmenu, NULL, set_fspeed, clock_speed(st->clk), 0, 5, st );
ment.speed = menu_addknob( pmenu, NULL, set_speed, clock_speed(st->clk), .5, 5, st );
ment.step = menu_addknob( pmenu, NULL, set_step, clock_time(st->clk), 0, 10, st );
ment.fwd = menu_addtoggle( pmenu, NULL, set_fwd, clock_fwd(st->clk), 2, st );
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
#endif
#ifndef NO_WHERE
ment.where[0] = menu_addentry( pmenu, "", NULL, NULL );
ment.where[1] = menu_addentry( pmenu, "", NULL, NULL );
ment.where[2] = menu_addentry( pmenu, "", NULL, NULL );
ment.where[3] = menu_addentry( pmenu, "", NULL, NULL );
#endif
ment.every = menu_addknob( pmenu, NULL, set_every, st->subsample, 1, 10, st );
menu_addentry( pmenu, " ", NULL, NULL );
ment.setscale = menu_addknob( pmenu, NULL, set_scale, 0., -4., 1., st );
if(strstr(menuopt, "viewall"))
ment.viewall = menu_addtoggle( pmenu, NULL, set_viewall, 0, 2, st );
menu_addentry( pmenu, " ", NULL, NULL );
ment.box = menu_addtoggle( pmenu, NULL, set_allboxes, st->useboxes, 3, st );
menu_addentry( pmenu, " ", NULL, NULL );
{
struct boxleveler *blev = NewN( struct boxleveler, COUNT(ment.boxlevel) );
for(i = 0; i < COUNT(ment.boxlevel); i++) {
blev[i].st = st;
blev[i].level = i;
ment.boxlevel[i] = menu_addtoggle( pmenu, NULL, set_boxlevel, 1, 2,
&blev[i] );
}
}
ment.menu = menu_addtoggle( pmenu, "<Menu>", set_menu, 0, 2, st );
menu_addentry( pmenu, " ", NULL, NULL );
stubmenu = menu_create( .05, .15 );
menu_addtoggle( stubmenu, "<Menu>", set_menu, 0, 2, st );
menu_sethidden( stubmenu, 1 );
#endif /*NOCAVE*/
return st;
}
#if CAVEMENU
void specks_refresh_menu(struct stuff *st)
{
int i;
#if MENU_IN_PPR
menu_check( pmenu, pmenu->cavewall );
menu_check( stubmenu, stubmenu->cavewall );
#endif
menu_sethidden( pmenu, st->hidemenu || empty );
menu_sethidden( stubmenu, st->hidemenu<=0 || empty );
if(st->vdcmd[0] != '\0') {
VIDI_queue_commandstr( st->vdcmd );
st->vdcmd[0] = '\0';
}
set_psize( st->psize, ment.psize, st );
set_lumvar( st->sizedby, ment.lumvar, st );
set_colorvar( st->coloredby, ment.colorvar, st );
set_slum( st->vdesc[st->curdata][st->sizedby].lum, ment.slum, st );
set_every( st->subsample, ment.every, st );
set_scale( ment.setscale->val, ment.setscale, st );
if(ment.label) set_label( st->usetext, ment.label, st );
if(ment.poly) set_poly( st->usepoly, ment.poly, st );
if(ment.annot)
menu_settitle( ment.annot, st->annotation ? st->annotation : " " );
if(st->ntimes > 1) {
menu_setknobrange( ment.step, 0, st->ntimes-1 );
set_fwd( st->timefwd, ment.fwd, st );
set_step( st->time0, ment.step, st );
697
698
699
700
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
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
} else {
menu_settitle( ment.fwd, "" );
menu_settitle( ment.step, "" );
menu_settitle( ment.speed, "" );
if(ment.viewall)
menu_settitle( ment.viewall, "" ); /* no need to "view peak", right? */
}
if(st->ndata > 1) {
set_seedata( st->curdata, ment.seedata, st );
} else {
menu_settitle( ment.seedata, "" );
}
if(st->boxlevels > 0) {
set_allboxes( st->useboxes, ment.box, st );
} else {
menu_settitle( ment.box, "" );
}
if(ment.tknob[0]) /* if SC99DEMO, i.e. if PARTIMENU includes "survey" */
for(i = 0; i < 3; i++)
set_tknob( ment.tknob[i]->val, ment.tknob[i], ment.tknob[i]->data );
#ifndef NO_WHERE
for(i = 0; i < COUNT(ment.where) && ment.where[i] != NULL; i++)
set_where( i, ment.where[i], st );
#endif
/* Publicize our menu location so other apps -- Matt's vtk AMR code --
* can avoid interacting if user's wand points there.
*/
parti_menuwall = pmenu->cavewall;
parti_menubox[0] = pmenu->x0 * pmenu->wallxpix;
parti_menubox[1] = ((pmenu->y0 < pmenu->y1) ? pmenu->y0 : pmenu->y1)
* pmenu->wallypix;
parti_menubox[2] = pmenu->x1 * pmenu->wallxpix;
parti_menubox[3] = ((pmenu->y0 > pmenu->y1) ? pmenu->y0 : pmenu->y1)
* pmenu->wallypix;
}
void specks_evoke_menu( struct stuff *st ) {
menu_evoke( pmenu ); /* evoke any callbacks */
}
#endif /*CAVEMENU*/
void specks_rethresh( struct stuff *st, struct specklist *sl, int by )
{
struct valdesc *vd;
int i;
int curdata = st->curdata;
int nel = sl->nspecks;
float cmin, cmax, normal;
int ncmap = st->ncmap;
int index;
int min, max;
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;
for(i = 0, p = sl->specks; i < sl->nspecks; i++, p = NextSpeck( p, sl, 1 )) {
if((min&&p->val[by]<threshmin) || (max&&p->val[by]>threshmax)) {
p->rgba |= THRESHBIT;
} else {
p->rgba &= ~THRESHBIT;
changed |= was ^ sel[i];
}
if(changed) {
sl->selseq++;
if(st->selseq < sl->selseq) st->selseq = sl->selseq;
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
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;
}
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
}
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 );