Skip to content
Snippets Groups Projects
partibrains.c 205 KiB
Newer Older
#ifdef __cplusplus
extern "C" {	// in case someone feeds this to the C++ compiler,...
#endif

slevy's avatar
 
slevy committed
static char local_id[] = "$Id$";
slevy's avatar
slevy committed
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.
slevy's avatar
slevy committed
 * This file is part of partiview, released under the
 * Illinois Open Source License; see the file LICENSE.partiview for details.
slevy's avatar
 
slevy committed
/*
 * $Log$
 * Revision 1.124  2011/01/19 21:59:55  slevy
 * Add partially-baked stuff for glDrawElements()/glDrawArrays() prep for POLYMESH objects.
 * Not in use yet.
 *
 * Add "vec/vectors" and "vecscale" control commands and "vecvar" data command.
 * When enabled, draws a vector at each point, as specified by some
 * triple of attributes given by "vecvar".  Length is [vecvar .. vecvar+2]
 * scaled by vecscale (default 1).
 *
 * Revision 1.123  2009/06/26 08:38:46  slevy
 * Add -w option on mesh object -- set linewidth.
 *
 * Revision 1.122  2008/07/25 16:04:19  slevy
 * Rename getline() to get_line(), avoiding collision with new C lib function.
 *
 * Revision 1.121  2008/07/22 18:48:03  slevy
 * CONSTify char *'s in parse_selexpr() and a few other places.
 * Explicitly (int) when we've parsed into a float.
 *
 * Revision 1.120  2006/05/03 01:48:26  slevy
 * Add Usage messages for "hist" and "waveobj".
 * Interpret threshholding correctly for "hist".
 * Make "thresh off" finally work again, too.  Good grief.
 *
 * Revision 1.119  2006/03/29 18:16:42  slevy
 * Make "where" command report cam-to-obj as well as cam-to-world transforms.
 *
 * Revision 1.118  2006/02/09 07:34:12  slevy
 * Need conste.h if we're doing USE_CONSTE.
 *
 * Revision 1.117  2006/01/17 07:37:11  slevy
 * Move some specklist-maintenance functions to specks.c.
 * Work in a way compatible with locking.
 *
 * Revision 1.116  2005/12/14 20:47:31  slevy
 * Think we have a workaround for Apple/GLX glDrawInterleavedArrays()
 * bug, so remove the Apple-specific workaround.
 *
 * Revision 1.115  2005/11/30 00:09:29  slevy
 * Use separate color and vertex arrays instead of glInterleavedArrays(),
 * which seems to have bugs on some implementations (?!).
 * Let's see if this helps.
 *
 * Revision 1.114  2005/10/18 21:22:53  slevy
 * Discard excess glBegin()/glEnd()'s from drawspecks()'s oldopengl path.
 * Add env var PARTIOLDOPENGL to force using non-glDrawElements path.
 *
 * Revision 1.113  2005/06/13 18:12:07  slevy
 * Fix long-standing bug where polygons would get the wrong orientation
 * if some were fixed-oriented and others screen-facing.
 * Portability tweak from Toshi -- be even more pessimistic about stack size.
 *
 * Revision 1.112  2005/02/08 20:10:59  slevy
 * Force using oldopengl (no glInterleavedArrays()/glDrawElements()) on MacOS X --
 * it seems to get the data completely wrong (most X's = 0, etc.).
 * If someone ever figures out why, I'd be curious to know.
 *
 * Revision 1.111  2004/10/19 01:52:27  slevy
 * Give specks_ieee_server() the right type to be an sproc function.
 * Need config.h early.
 * Initialize "oldopengl".
 * More digits for "where".
 *
slevy's avatar
slevy committed
 * Revision 1.110  2004/10/06 05:35:19  slevy
 * Add 3-D texturing.
 *
 * Revision 1.109  2004/07/26 16:44:50  slevy
 * specks_set_byvariable() now correctly fails on 0-length names.
 *
 * Revision 1.108  2004/07/26 04:33:01  slevy
 * Use vertex arrays for drawing points, if available.
 * Allow dyndata processors to switch themselves off with st->dyn.enabled = -1.
 *
 * Revision 1.107  2004/07/23 20:57:12  slevy
 * Move alloca boilerplate (ugh) earlier.
 * Use HAVE_SQRTF.
 *
 * Revision 1.106  2004/07/06 23:06:22  slevy
 * Make use of multiple timesteps even if we have a dyndata handler.
 *
 * Revision 1.105  2004/04/19 21:04:12  slevy
 * Un-CONST-ify most of what had been constified.  It's just too messy.
 *
 * Revision 1.104  2004/04/19 17:42:42  slevy
 * Use AC_FUNC_ALLOCA and the autoconf-standard alloca boilerplate
 * in each of the files that uses alloca.
 *
 * Revision 1.103  2004/04/12 19:09:54  slevy
 * Crank up default specular highlights.
 * CONSTify getfloats().
 *
 * Revision 1.102  2004/01/14 02:03:41  slevy
 * Add Chromatek color-coding of depth, contributed by Carl Hultquist
 * (chultquist@smuts.uct.ac.za, student of Anthony Fairall), as part of his
 * Computer Science Honours project.  Works with Chromatek glasses,
 * which make red things look nearby, blue things far away.
 * New commands:
 *    chromadepth {on|off}
 * 	replaces colors of points and polygons with depth-coded colors
 *    chromaparams ZSTART ZRANGE
 * 	sets Z-range (distance from camera plane) over which
 * 	colormapping applies.  Z=ZSTART maps to first entry,
 * 	Z=ZSTART+ZRANGE maps to last entry in colormap.
 *    chromacmap  FILE.CMAP
 * 	Specifies colormap.
 * See example files data/chromadepth.cmap and data/hipchroma.
 *
 * Revision 1.101  2004/01/09 13:32:06  slevy
 * Parse lum command correctly again...
 *
slevy's avatar
slevy committed
 * Revision 1.100  2004/01/09 04:54:46  slevy
 * Add lum options:
 *    "all"  - revert to autoranging
 *    "abs [base]"  - lum = scalefactor * abs(value - base)
 *    "lin"  - default behavior (unsets any "abs")
 *
 * Revision 1.99  2003/12/10 19:38:05  slevy
 * Add "pb" datacommand to read partadv-style .pb files.  Finally, a general-purpose
 * binary particle format!
 *
 * Revision 1.98  2003/11/03 17:06:55  smarx
 * small additions/changes to make os x and windows buildable and functional. open issues on windows time motion widgets and terminating cleanly.
 *
 * Revision 1.97  2003/10/26 16:20:22  slevy
 * Merge Steve Marx's many improvements -- generic slider,
 * MacOS X port, "home" command/button, lots of bug fixes -- into main branch!
 *
slevy's avatar
slevy committed
 * Revision 1.96  2003/10/25 00:42:52  slevy
 * Add "echo" data+control command.
 * Try to add pthread-based USE_IEEEIO.  Don't know if this works yet,
 * but it compiles.
 *
 * Revision 1.95  2003/09/30 08:44:37  slevy
 * Make waveobj accept objects made of line segments.
 * Revision 1.94.2.1  2003/05/15 14:58:57  smarx
 * rel_0_7_04 upgrades to fltk-1.1.3, build support for os x, os x middle mouse button keyboard simulation, os x workaround for partiview/fltk issues with proper redraw. this release is using a recent fltk-1.1.3 cvs upgrade - not the standard release - to resolve OpenGL bugs that will be in fltk-1.1.4. Note that this release of partiview requires fltk-1.1.x support which precludes use of the old file chooser
 * Revision 1.94  2003/02/15 06:55:57  slevy
 * Add "slvalid" flag to struct dyndata.  Don't just use currealtime as
 * the validity test.
 *
 * Revision 1.93  2002/10/04 00:50:21  slevy
 * Fix CAVE-text-alignment hack for non-CAVE case.
 *
 * Revision 1.92  2002/10/02 07:00:04  slevy
 * Change text orientation in THIEBAUX_VIRDIR (often multipipe CAVE)
 * mode.  Rather than having text be oriented per-graphics-window,
 * we choose the orientation of the master pipe.
 *
 * Revision 1.91  2002/07/20 15:53:03  slevy
 * Make wavefront .obj models work with (or without) texture coordinates
 * and/or vertex normals.
 *
 * Revision 1.90  2002/07/20 05:03:39  slevy
 * Support textures and per-vertex normals from "waveobj" files.
 *
 * 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.
 *
slevy's avatar
slevy committed
 * 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.
 *
slevy's avatar
slevy committed
 * 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!
 *
slevy's avatar
slevy committed
 * 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.
 *
slevy's avatar
slevy committed
 * 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.
 *
slevy's avatar
slevy committed
 * 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.
 *
slevy's avatar
slevy committed
 * 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.
 *
slevy's avatar
slevy committed
 * Revision 1.26  2001/02/22 20:04:34  slevy
 * CONSTify.
 *
 * 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.
slevy's avatar
 
slevy committed
 *
 * Revision 1.18  2001/02/03 23:43:10  slevy
slevy's avatar
 
slevy committed
 * Don't let "kira tree" hide "kira track" -- demand 3 chars!
 *
slevy's avatar
 
slevy committed
 * Revision 1.17  2001/02/03 16:49:42  slevy
 * Update cookedcmap when "cment" changes cmap.
 *
slevy's avatar
 
slevy committed
 * Revision 1.16  2001/02/03 15:29:03  slevy
 * Toss unused variable.
 *
slevy's avatar
 
slevy committed
 * 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.
 *
slevy's avatar
 
slevy committed
 * Revision 1.14  2001/01/31 17:11:54  slevy
 * Ensure that, for starlab, clock is always in "continuous" mode.
 *
slevy's avatar
 
slevy committed
 * Revision 1.13  2001/01/31 17:07:12  slevy
 * Add RCS Id and Log strings.
 *
 */
teuben's avatar
teuben committed

#define __USE_MISC	/* makes <math.h> define sqrtf() on GNU libc */

#ifndef __GNUC__
# if HAVE_ALLOCA_H
#  include <alloca.h>
# else
#  ifdef _AIX
  #pragma alloca
#  else
#   ifndef alloca /* predefined by HP cc +Olibcalls */
extern void *alloca(int);
#   endif
#  endif
# endif
#endif

#ifdef HAVE_MALLOC_H
#include <malloc.h>	/* for mallinfo(), amallinfo(), maybe alloca() too */
#endif

teuben's avatar
teuben committed
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>

#if !defined(HAVE_SQRTF)
teuben's avatar
teuben committed
# 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 */
slevy's avatar
 
slevy committed
# include <time.h>
slevy's avatar
 
slevy committed
# ifndef WORDS_BIGENDIAN
#  include "config.h"	/* for WORDS_BIGENDIAN */
# endif
slevy's avatar
slevy committed
# if USE_IEEEIO
#  include <sys/prctl.h>
#  ifndef PR_SADDR		/* if SGI, use sproc() for bg processing */
#    define USE_PTHREAD  1	/* linux or other UNIX; use pthreads for bg */
#    include <pthread.h>
#  endif  /* end non-SGI */
# endif   /* end USE_IEEEIO */

teuben's avatar
teuben committed
#else /*WIN32*/
# include "winjunk.h"
slevy's avatar
 
slevy committed
# define WORDS_BIGENDIAN 0
teuben's avatar
teuben committed
#endif
teuben's avatar
teuben committed
#include <string.h>
#include <errno.h>

slevy's avatar
 
slevy committed

slevy's avatar
 
slevy committed
#if WORDS_BIGENDIAN
teuben's avatar
teuben committed
#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)
teuben's avatar
teuben committed
#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)
teuben's avatar
teuben committed
#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)

teuben's avatar
teuben committed
#include "geometry.h"

#ifdef __APPLE__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>    /* for GLuint */
#endif
teuben's avatar
teuben committed

#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>

teuben's avatar
teuben committed
#ifdef USE_KIRA
#include "kira_parti.h"
#ifdef USE_CONSTE
#include "conste.h"
#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"
teuben's avatar
teuben committed
#endif

  /* Star Renderer (.sdb) structure -- from stardef.h */
typedef enum {ST_POINT, ST_BRIGHT_CLOUD ,ST_DARK_CLOUD, ST_BOTH_CLOUD, ST_OFF} stype;
teuben's avatar
teuben committed

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_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[] );
slevy's avatar
 
slevy committed
int specks_cookcment( struct stuff *st, int cment );
void specks_rgbremap( struct stuff *st );
teuben's avatar
teuben committed

slevy's avatar
 
slevy committed
void specks_reupdate( struct stuff *st, struct specklist *sl );
teuben's avatar
teuben committed
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 );
slevy's avatar
 
slevy committed
void specks_timerange( struct stuff *st, double *tminp, double *tmaxp );
teuben's avatar
teuben committed

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);
  }

teuben's avatar
teuben committed
  memset(st, 0, sizeof(*st));
  st->spacescale = 1.0;
  st->fog = 0;
  st->psize = 1;
  st->alpha = .5;
  st->gamma = defgamma;
slevy's avatar
 
slevy committed
  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 );
teuben's avatar
teuben committed
  st->useme = 1;
  st->usepoly = 0;
  st->usepoint = 1;
  st->usevec = 0;
  st->vecvar0 = 0;
  st->vecscale = 1.0f;
teuben's avatar
teuben committed
  st->usetext = 1;
  st->usetextaxes = 1;
  st->usetextures = 1;
  st->useboxes = 1;
  st->usemeshes = 1;
  st->staticmeshes = NULL;
  st->mullions = 0;
  st->useellipsoids = 1;
teuben's avatar
teuben committed
  st->polysizevar = -1;
  st->polyarea = 0;
  st->polyorivar0 = -1;
  st->use_chromadepth = 0;
  st->chromaslidestart = 2.0;
  st->chromaslidelength = 20;
teuben's avatar
teuben committed
  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;
slevy's avatar
 
slevy committed
  st->everycomp = 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;
teuben's avatar
teuben committed

  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;
teuben's avatar
teuben committed
  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));
slevy's avatar
 
slevy committed
  for(i = 0; i < COUNT(defcmap); i++) {
    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 );
slevy's avatar
 
slevy committed
  }
  /* 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 );
teuben's avatar
teuben committed

  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 );

teuben's avatar
teuben committed
  st->ntimes = 0;
  st->ndata = 0;
  st->curtime = 0;
  st->curdata = 0;
  st->datatime = 0;
slevy's avatar
 
slevy committed
  st->usertrange = 0;
  st->utmin = -HUGE;
  st->utmax = HUGE;
  st->utwrap = 0.1;
teuben's avatar
teuben committed
  st->sl = NULL;

  st->boxes = NULL;
  st->boxlevels = 0;
  st->boxlinewidth = 0.75;

slevy's avatar
 
slevy committed
  st->depthsort = 0;

slevy's avatar
 
slevy committed
  st->clk = NewN(SClock, 1);
  clock_init(st->clk);
  clock_set_running(st->clk, 1);
teuben's avatar
teuben committed

  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));
teuben's avatar
teuben committed

#if CAVE
  shmrecycler( specks_purge, st );
#endif

  for(i = 1; i < argc; i++)
    specks_read( &st, argv[i] );

  IFCAVEMENU( partimenu_init( st ) );
teuben's avatar
teuben committed

  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;
  SelOp threshseldest;
  int changed = 0;
teuben's avatar
teuben committed

  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;
teuben's avatar
teuben committed

  for(i = 0, p = sl->specks; i < nel; i++, p = NextSpeck( p, sl, 1 )) {
    SelMask was = sel[i];
    if((min&&p->val[by]<threshmin) || (max&&p->val[by]>threshmax)) {
	SELUNSET( sel[i], &threshseldest );
	SELSET( sel[i], &threshseldest );
    changed |= was ^ sel[i];
  }
  if(changed) {
    sl->selseq++;
    if(st->selseq < sl->selseq) st->selseq = sl->selseq;
teuben's avatar
teuben committed
  }
}

slevy's avatar
 
slevy committed
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);
slevy's avatar
 
slevy committed
    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 );

  /* and chromadepth colormaps */
  if (st->chromacm != NULL) {
    for (i = 0; i < st->nchromacm; i++)
	st->chromacm[i].cooked = specks_cookcment(st, st->chromacm[i].raw);
  }
slevy's avatar
 
slevy committed
  st->colorseq++;
}


teuben's avatar
teuben committed
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;
teuben's avatar
teuben committed
  int index;
  int rgb565;
slevy's avatar
 
slevy committed
  unsigned char (*rgbmap)[256];
teuben's avatar
teuben committed

  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];
slevy's avatar
 
slevy committed
    int r, g, b, rgba;
teuben's avatar
teuben committed
    vd = &st->vdesc[curdata][CONSTVAL];
slevy's avatar
 
slevy committed
    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[1][g];
    crgba[2] = st->rgbmap[2][b];
teuben's avatar
teuben committed
    crgba[3] = 0;
slevy's avatar
 
slevy committed
    rgba = *(int *)&crgba[0];	/* XXX 64-bit bug? */
teuben's avatar
teuben committed
    for(i = 0; i < nel; i++, sp = NextSpeck(sp, sl, 1)) {
	sp->rgba = rgba | (sp->rgba & EXTRABITS);
teuben's avatar
teuben committed
    }
    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;
  }

teuben's avatar
teuben committed

  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");