From 4bbee7652732567abfbc7d5e1160516b6ac68e2a Mon Sep 17 00:00:00 2001 From: slevy <slevy> Date: Thu, 25 Jan 2001 00:27:21 +0000 Subject: [PATCH] "depthsort" adds depth-sorted polygons. New texture qualifiers -i(ntensity) -a(lpha) -A(dd). New "gall" (a.k.a. "allobj") cmd sends following command to all objects. "everycomp" says whether to compensate for "every" subsampling. --- src/partibrains.c | 295 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 269 insertions(+), 26 deletions(-) diff --git a/src/partibrains.c b/src/partibrains.c index c9c900f..88dcb8a 100644 --- a/src/partibrains.c +++ b/src/partibrains.c @@ -18,8 +18,11 @@ # include <unistd.h> # include <sys/types.h> # include <netinet/in.h> /* for htonl */ +# include <time.h> # include <alloca.h> -# include "config.h" /* for WORDS_BIGENDIAN */ +# ifndef WORDS_BIGENDIAN +# include "config.h" /* for WORDS_BIGENDIAN */ +# endif #else /*WIN32*/ # include "winjunk.h" # define WORDS_BIGENDIAN 0 @@ -221,6 +224,7 @@ specks_init( int argc, char *argv[] ) st->textsize = .05; st->npolygon = 11; st->subsample = 1; + st->everycomp = 1; st->menudemandfps = 4.0; @@ -270,6 +274,8 @@ specks_init( int argc, char *argv[] ) st->boxlevels = 0; st->boxlinewidth = 0.75; + st->depthsort = 0; + st->clk = NewN(SClock, 1); clock_init(st->clk); clock_set_running(st->clk, 1); @@ -970,7 +976,7 @@ void specks_timerange( struct stuff *st, double *tminp, double *tmaxp ) #endif ) { *tminp = 0; - *tmaxp = st->ntimes + 1; + *tmaxp = st->ntimes == 0 ? 0 : st->ntimes - 1; } } @@ -1108,6 +1114,7 @@ void specks_set_time( struct stuff *st, double newtime ) #if CAVE if(ment.tknob[0] == NULL) { /* if not SC99DEMO */ + struct specklist *sl = st->sl; if(sl != NULL && memcmp(&sl->interest, &lastinterest, sizeof(Point)) && (sl->interest.x[0]!=0 || sl->interest.x[1]!=0 || sl->interest.x[2]!=0)) { @@ -1248,6 +1255,217 @@ void dumpcpoints( struct cpoint *cp, int n ) } } +static Point depth_fwd; +static float depth_d; + +struct order { + float z; + struct speck *sp; + struct specklist *sl; +}; + +static int depthcmp( const void *a, const void *b ) +{ + return ((struct order *)a)->z < ((struct order *)b)->z ? 1 + : ((struct order *)a)->z > ((struct order *)b)->z ? -1 : 0; +} + +static int additive_blend; + +void sortedpolys( struct stuff *st, struct specklist *slhead, Matrix *Tc2wp, float radperpix, float polysize ) +{ + struct speck *sp, *sbase; + struct order *op, *obase; + int i, k, total, skip; + struct specklist *sl; + int usethresh = st->usethresh&P_USETHRESH ? THRESHBIT : 0; + int bps = 0; + int prevrgba = -1; + int usearea = st->polyarea; + int sizevar = st->polysizevar; + int polyorivar = st->polyorivar0; + int texturevar = st->texturevar; + int txno; + int texturing = -1; + float s; + float polyminrad = st->polymin * radperpix; + float polymaxrad = st->polymax * radperpix; + float mins2d = polyminrad * polyminrad; + int rgba; + int alpha = st->alpha * 255; + int nfan = st->npolygon<MAXXYFAN ? st->npolygon : MAXXYFAN; + float xyfan[MAXXYFAN][2]; + Point sfan[MAXXYFAN], pfan[MAXXYFAN]; + Matrix Tc2w = *Tc2wp; + float scl = vlength( (Point *)&Tc2w.m[0*4+0] ); + Texture *wanttx; + int additive = additive_blend; + int wantblend = additive; + + int useclip = (st->clipbox.level > 0); + Point clipp0 = st->clipbox.p0; + Point clipp1 = st->clipbox.p1; + + for(total = 0, sl = slhead; sl != NULL; sl = sl->next) { + if(sl->text != NULL || sl->nspecks == 0 || sl->special != SPECKS) + continue; + skip = st->subsample; + if(sl->subsampled != 0) /* if already subsampled */ + skip /= sl->subsampled; + if(skip <= 0) skip = 1; + + if(bps < sl->bytesperspeck) bps = sl->bytesperspeck; + if(usethresh) { + for(i=sl->nspecks, sp=sl->specks; i>0; i-=skip, sp=NextSpeck(sp,sl,skip)) { + if((usethresh & sp->rgba) == 0) + total++; + } + } else { + total += sl->nspecks / skip; + } + } + + obase = op = (struct order *)malloc( (total+1) * sizeof(struct order) ); + for(sl = slhead; sl != NULL; sl = sl->next) { + if(sl->text != NULL || sl->nspecks == 0 || sl->special != SPECKS) + continue; + skip = st->subsample; + if(sl->subsampled != 0) /* if already subsampled */ + skip /= sl->subsampled; + if(skip <= 0) skip = 1; + for(i=sl->nspecks, sp=sl->specks; i > 0; i-=skip, sp=NextSpeck(sp,sl,skip)) { + float dist; + if(usethresh & sp->rgba) + continue; + dist = VDOT( &sp->p, &depth_fwd ) + depth_d; + if(dist < 0) + continue; + if(useclip && + (sp->p.x[0] < clipp0.x[0] || + sp->p.x[0] > clipp1.x[0] || + sp->p.x[1] < clipp0.x[1] || + sp->p.x[1] > clipp1.x[1] || + sp->p.x[2] < clipp0.x[2] || + sp->p.x[2] > clipp1.x[2])) + continue; + op->z = dist; + op->sp = sp; + op->sl = sl; + op++; + } + } + + total = op - obase; + qsort( obase, total, sizeof(*obase), depthcmp ); + + prevrgba = 0; + + /* Build prototype fan -- unit disk in screen plane */ + for(i = 0; i < nfan; i++) { + float theta = 2*M_PI*i/nfan; + xyfan[i][0] = cos(theta); + xyfan[i][1] = sin(theta); + vcomb( &sfan[i], xyfan[i][0] / scl, (Point *)&Tc2w.m[0*4+0], + xyfan[i][1] / scl, (Point *)&Tc2w.m[1*4+0] ); + } + + if(st->usetextures == 0 || SMALLSPECKSIZE(texturevar) > bps) + texturevar = -1; + if(SMALLSPECKSIZE(polyorivar) > bps) + polyorivar = -1; + + for(i = 0, op = obase; i < total; i++, op++) { + float dist, size; + + sp = op->sp; + dist = op->z; + size = sp->val[sizevar] * polysize; + if(usearea) { + if(size < dist * dist * mins2d) + continue; + size = sqrtf(size); + } else { + if(size < dist * polyminrad) + continue; + } + if(size > dist * polymaxrad) + size = dist * polymaxrad; + + rgba = sp->rgba & ~THRESHBIT; + if(rgba != prevrgba) { + prevrgba = rgba; + rgba = RGBALPHA( prevrgba, alpha ); + glColor4ubv( (GLubyte *)&rgba ); + } + + if(texturevar >= 0 && + (txno = sp->val[texturevar]) >= 0 && + txno < st->ntextures && + (wanttx = st->textures[txno]) != NULL) { + + txbind( wanttx, &texturing ); + wantblend = (wanttx->flags & TXF_ADD) ? 1 : additive_blend; + } else if(texturing) { + glDisable( GL_TEXTURE_2D ); + texturing = 0; + } + + if(wantblend != additive) { + additive = wantblend; + glBlendFunc( GL_SRC_ALPHA, additive ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA ); + } + + if(polyorivar >= 0 && sp->val[polyorivar] < 9) { + float *xv = &sp->val[polyorivar]; + float *yv = &sp->val[polyorivar+3]; + + glBegin( GL_TRIANGLE_FAN ); + if(texturing) { + for(k = 0; k < nfan; k++) { + glTexCoord2fv( &xyfan[k][0] ); + glVertex3f( + sp->p.x[0] + size*(xyfan[k][0]*xv[0] + xyfan[k][1]*yv[0]), + sp->p.x[1] + size*(xyfan[k][0]*xv[1] + xyfan[k][1]*yv[1]), + sp->p.x[2] + size*(xyfan[k][0]*xv[2] + xyfan[k][1]*yv[2])); + } + } else { + for(k = 0; k < nfan; k++) { + glVertex3f( + sp->p.x[0] + size*(xyfan[k][0]*xv[0] + xyfan[k][1]*yv[0]), + sp->p.x[1] + size*(xyfan[k][0]*xv[1] + xyfan[k][1]*yv[1]), + sp->p.x[2] + size*(xyfan[k][0]*xv[2] + xyfan[k][1]*yv[2])); + } + } + glEnd(); + + } else { + glBegin( GL_TRIANGLE_FAN ); + if(texturing) { + for(k = 0; k < nfan; k++) { + glTexCoord2fv( &xyfan[k][0] ); + glVertex3f( + sp->p.x[0] + size*sfan[k].x[0], + sp->p.x[1] + size*sfan[k].x[1], + sp->p.x[2] + size*sfan[k].x[2] ); + } + } else { + for(k = 0; k < nfan; k++) { + glVertex3f( + sp->p.x[0] + size*sfan[k].x[0], + sp->p.x[1] + size*sfan[k].x[1], + sp->p.x[2] + size*sfan[k].x[2] ); + } + } + glEnd(); + } + } + free(obase); + if(texturing > 0) + txbind( NULL, NULL ); +} + + + void drawspecks( struct stuff *st ) { int i, slno, k; @@ -1271,7 +1489,6 @@ void drawspecks( struct stuff *st ) int randix = 0; int fast = st->fast; int inpick = st->inpick; - int additive_blend = 1; int usethresh = st->usethresh&P_USETHRESH ? THRESHBIT : 0; int fixeddist; float polyminrad, polymaxrad; @@ -1312,12 +1529,10 @@ void drawspecks( struct stuff *st ) } -#if !CAVEMENU { float r=0,g=0,b=0; /* Ugh. Allow background to be non-black */ - sscanf(parti_bgcolor(NULL), "%f %f %f", &r,&g,&b); - if(r+g+b > 0) additive_blend = 0; + sscanf(parti_bgcolor(NULL), "%f%f%f", &r,&g,&b); + additive_blend = (r+g+b == 0); } -#endif if(st->clipbox.level != 0) { GLdouble plane[4]; @@ -1436,7 +1651,7 @@ void drawspecks( struct stuff *st ) && st->vdesc[st->curdata][st->sizedby].lum != 0) { plum *= st->vdesc[st->curdata][st->sizedby].lum; } - if(st->subsample > 0) + if(st->subsample > 0 && st->everycomp) plum *= st->subsample; /* Compensate for "every" subsampling */ @@ -1452,6 +1667,7 @@ void drawspecks( struct stuff *st ) if(inpick) glLoadName(0); + if(st->usepoly && st->polysize > 0) { int texturing = 0; int texturevar = st->usetextures && st->texturevar >= 0 @@ -1483,11 +1699,17 @@ void drawspecks( struct stuff *st ) && (unsigned int)st->curdata < MAXFILES && st->vdesc[st->curdata][st->sizedby].lum != 0) polysize *= st->vdesc[st->curdata][st->sizedby].lum; - if(st->subsample > 0) + if(st->subsample > 0 && st->everycomp) polysize *= st->subsample; /* Compensate for "every" subsampling */ } - for(sl = slhead, slno = 1; sl != NULL; sl = sl->next, slno++) { + if(st->depthsort && !inpick) { + depth_fwd = fwd; + depth_d = fwdd; + sortedpolys( st, slhead, &Tc2w, radperpix, polysize ); + + } else { + for(sl = slhead, slno = 1; sl != NULL; sl = sl->next, slno++) { if(sl->text != NULL || sl->special != SPECKS) continue; if(inpick) { glLoadName(slno); @@ -1529,10 +1751,8 @@ void drawspecks( struct stuff *st ) } else if(p->size != prevsize) { float s = scl*size; for(k = 0; k < nxyfan; k++) { - tp.x[0] = s*xyfan[k][0]; - tp.x[1] = s*xyfan[k][1]; - tp.x[2] = 0; - vtfmvector( &fan[k], &tp, &Tc2w ); + vcomb( &fan[k], s*xyfan[k][0], (Point *)&Tc2w.m[0*4+0], + s*xyfan[k][1], (Point *)&Tc2w.m[1*4+0] ); } prevsize = size; } @@ -1548,7 +1768,7 @@ void drawspecks( struct stuff *st ) glEnd(); } else if(texturevar >= 0 - && (txno = (p->val[texturevar] - 1)) >= 0 + && (txno = p->val[texturevar]) >= 0 && txno < st->ntextures && st->textures[txno] != NULL) { @@ -1575,9 +1795,10 @@ void drawspecks( struct stuff *st ) } if(inpick) glPopName(); + } } if(texturing) { - txload( NULL ); + txbind( NULL, NULL ); glDisable( GL_TEXTURE_2D ); } glMatrixMode( GL_TEXTURE ); @@ -1821,7 +2042,7 @@ void drawspecks( struct stuff *st ) glBegin( GL_POINTS ); for(sl = slhead; sl != NULL; sl = sl->next) { if(sl->text != NULL || sl->special != SPECKS) continue; - for(i = 0, p = sl->specks; i < sl->nspecks; i+=skip, p= NextSpeck(p, sl, skip)) { + for(i = 0, p = sl->specks; i < sl->nspecks; i+=skip, p=NextSpeck(p,sl,skip)) { int lum, myalpha; float dist, dist2, dx, dy, dz; @@ -2664,23 +2885,31 @@ void specks_read( struct stuff **stp, char *fname ) while(--k >= 0) free(path[k]); } else if(!strcmp(key, "texture")) { - int txno; + int txno = 0; int txflags = TXF_SCLAMP | TXF_TCLAMP; int txapply = TXF_DECAL; int qual = 7; char *txfname; key = strtok(NULL, separ); - while(key != NULL && key[0] == '-') { - qual |= (strchr(key,'m') ? 4:0) | (strchr(key,'l') ? 2:0) | (strchr(key,'n') ? 1:0); + sscanf(key, "%d", &txno); + while(key != NULL && (key[0] == '-' || key[0] == '+')) { + int tqual = (strchr(key,'m') ? 4:0) | + (strchr(key,'l') ? 2:0) | + (strchr(key,'n') ? 1:0); + if(key[0] == '-') qual &= ~tqual; + else qual |= tqual; + if(strchr(key,'a')) txflags |= TXF_ALPHA; + if(strchr(key,'i')) txflags |= TXF_INTENSITY; + if(strchr(key, 'A')) txflags |= TXF_ADD; if(strchr(key, 'M')) txapply = TXF_MODULATE; if(strchr(key, 'D')) txapply = TXF_DECAL; if(strchr(key, 'B')) txapply = TXF_BLEND; key = strtok(NULL, separ); } - if(key == NULL || sscanf(key, "%d", &txno) <= 0 + if(key == NULL || (txno == 0 && sscanf(key, "%d", &txno) <= 0) || (txfname = strtok(NULL, separ)) == NULL) { - msg("Expected ``texture [-lmnMDB] txno file.sgi'', got %s", oline); - msg(" (options -l(inear) -m(ipmap) -n(earest) -M(odulate)|-D(ecal)|-B(lend))"); + msg("Expected ``texture [-lmnaMDB] txno file.sgi'', got %s", oline); + msg(" opts: -l(inear) -m(ipmap) -n(earest) -i(intensity) -a(lpha) -A(dd) -M(odulate)|-D(ecal)|-B(lend))"); } else { txaddentry( &st->textures, &st->ntextures, fname, txno, txfname, txapply, txflags, qual ); } @@ -3156,7 +3385,7 @@ void set_step( float time0, MenuEnt *me, void *vst ) { st->timeplay = 0; me->state = ME_HELD; } - clock_set_time( me->val = (int) time0 ); + clock_set_time( st->clk, me->val = (int) time0 ); /* NOTE we use the static values snapped by the framefunction. * st->curtime etc. might have changed since then. */ @@ -3167,7 +3396,7 @@ void set_step( float time0, MenuEnt *me, void *vst ) { } void set_fwd( int fwd, MenuEnt *me, void *st ) { - clock_set_fwd( st->clk, fwd ); + clock_set_fwd( ((struct stuff *)st)->clk, fwd ); menu_settitle( me, fwd ? ">>> fwd >>>" : "<<< rev <<<" ); } @@ -3629,6 +3858,7 @@ int getbool( char *str, int defval ) { if(!strcasecmp(str, "on")) return 1; if(!strcasecmp(str, "off")) return 0; + if(!strcasecmp(str, "toggle")) return !defval; if(!strcasecmp(str, "all")) return -1; v = strtol(str, &ep, 0); if(str == ep) return defval; @@ -3688,12 +3918,13 @@ specks_parse_args( struct stuff **stp, int argc, char *argv[] ) " lum const LUM set all particles to be that brightness", " slum SCALEFACTOR scale particle size by SCALEFACTOR", " psize SIZE scale particle size by SIZE * SCALEFACTOR", +" depthsort sort polygons by depth", " see DATASETNO-or-NAME show that dataset (e.g. \"see 0\" or \"see gas\")", " read [-t time] DATAFILENAME read data file (e.g. to add new specks)", " ieee [-t time] IEEEIOFILE read IEEEIO file (starting at given timestep)", " sdb [-t time] SDBFILE read .sdb star-data file", " annot [-t time] string set annotation string (for given timestep)", -" eval DATAFILECOMMAND enter a single datafile command (ditto)", +" add DATAFILECOMMAND enter a single datafile command (ditto)", " every N subsample: show every Nth particle", " bound show bounds (coordinate range of all particles)", " clipbox {on | off | X0,X1 Y0,Y1 Z0,Z1 | CENX,Y,Z RADX,Y,Z | X0 Y0 Z0 X1 Y1 Z1} clipping region", @@ -3963,6 +4194,10 @@ specks_parse_args( struct stuff **stp, int argc, char *argv[] ) parti_set_running( st, getbool( argv[1], 1 ) ); st->playnext = 0.0; + } else if(!strcmp( argv[0], "depthsort" )) { + if(argc > 1) st->depthsort = getbool(argv[1], st->depthsort); + msg("depthsort %s", st->depthsort ? "on" : "off" ); + } else if(!strcmp( argv[0], "fade" )) { char *fmt = "fade what?"; if(argc>1) { @@ -4061,6 +4296,8 @@ specks_parse_args( struct stuff **stp, int argc, char *argv[] ) specks_count( st->sl )); } + } else if(!strcmp( argv[0], "gall" ) || !strncmp( argv[0], "allobj", 6 )) { + parti_allobjs( argc-1, argv+1 ); } else if(!strcmp(argv[0], "tfm")) { int inv = 0; @@ -4358,6 +4595,12 @@ specks_parse_args( struct stuff **stp, int argc, char *argv[] ) msg("display every %dth particle (of %d)", st->subsample, specks_count(st->sl)); + } else if(!strncmp( argv[0], "everycomp", 9 )) { + st->everycomp = getbool(argv[1], st->everycomp); + msg("everycomp %d (%s compensate for \"every\" subsampling)", + st->everycomp, + st->everycomp ? "do" : "don't"); + } else if(!strncmp( argv[0], "color", 5 )) { struct valdesc *vd; if(argc>1) { -- GitLab