--- ray/src/rt/RpictSimulManager.cpp 2024/08/21 23:32:24 2.5 +++ ray/src/rt/RpictSimulManager.cpp 2025/01/25 04:57:27 2.15 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: RpictSimulManager.cpp,v 2.5 2024/08/21 23:32:24 greg Exp $"; +static const char RCSid[] = "$Id: RpictSimulManager.cpp,v 2.15 2025/01/25 04:57:27 greg Exp $"; #endif /* * RpictSimulManager.cpp @@ -9,6 +9,8 @@ static const char RCSid[] = "$Id: RpictSimulManager.cp * Created by Greg Ward on 07/11/2024. */ +#define DEBUG 1 // XXX temporary! + #include #include "platform.h" #include "RpictSimulManager.h" @@ -103,8 +105,12 @@ RpictSimulManager::NewFrame(const VIEW &v, int xydim[2 if (!xydim) return false; if (!ap) ap = &pasp; - pvw = vw; // save previous view for motion blur - vw = v; + if (&v == &vw) { + pvw.type = 0; + } else { + pvw = vw; // save previous view for motion blur + vw = v; + } const char * verr = setview(&vw); if (verr) { error(WARNING, verr); @@ -196,14 +202,15 @@ RpictSimulManager::SetTile(const int ti[2]) bool RpictSimulManager::ComputePixel(int x, int y) { - static const SCOLOR scBlack = {0}; + DCHECK(doneMap.OffBitMap(x,y), + CONSISTENCY, "illegal pixel index in ComputPixel()"); int i; FVECT rodir[2]; double hpos = (x+pixjitter())/TWidth(); double vpos = (y+pixjitter())/THeight(); double dlim = viewray(rodir[0], rodir[1], &tvw, hpos, vpos); if (dlim < -FTINY) { // off view? - pacc.SetPixel(x, y, scBlack); + pacc.SetPixel(x, y, scblack); doneMap.Set(x, y); return true; } @@ -233,31 +240,37 @@ RpictSimulManager::ComputePixel(int x, int y) // Check if neighbor differences are below pixel sampling threshold bool -RpictSimulManager::BelowSampThresh(int x, int y, const int noff[4][2]) const +RpictSimulManager::BelowSampThresh(const int x, const int y, const int noff[4][2]) const { SCOLOR pval[4]; float dist[4]; int i, j; for (i = 4; i--; ) { // get pixels from tile store - int px = x + noff[i][0]; - int py = y + noff[i][1]; + const int px = x + noff[i][0]; + const int py = y + noff[i][1]; if (!doneMap.Check(px, py) || !pacc.GetPixel(px, py, pval[i], &dist[i])) return false; } - const bool spectr = (pacc.NC() > 3); - for (i = 4; --i; ) // do pairwise comparisons - for (j = i; j--; ) { - if (pacc.DepthType() && - (dist[i] - dist[j] > maxdiff*dist[j]) | + // do pairwise comparisons + for (i = (pacc.DepthType() != RDTnone)*4; --i > 0; ) + for (j = i; j--; ) + if ((dist[i] - dist[j] > maxdiff*dist[j]) | (dist[j] - dist[i] > maxdiff*dist[i])) return false; - if (spectr ? sbigsdiff(pval[i], pval[j], maxdiff) : - bigdiff(pval[i], pval[j], maxdiff)) + if (pacc.NC() > 3) { + for (i = 4; --i; ) + for (j = i; j--; ) + if (sbigsdiff(pval[i], pval[j], maxdiff)) return false; - } - return true; // linear interpolation OK + } else { + for (i = 4; --i; ) + for (j = i; j--; ) + if (bigdiff(pval[i], pval[j], maxdiff)) + return false; + } + return true; } // Fill an interior square patch with interpolated values @@ -268,9 +281,11 @@ RpictSimulManager::FillSquare(const int x, const int y float dist[4]; int i, j; // assumes 4 corners are valid! - for (i = 4; i--; ) + for (i = 4; i--; ) { + DCHECK(!doneMap.Check(x+noff[i][0], y+noff[i][1]), + CONSISTENCY, "inclusion of bad pixel in FillSquare()"); pacc.GetPixel(x+noff[i][0], y+noff[i][1], pval[i], &dist[i]); - + } i = abs(noff[1][0]-noff[0][0]); j = abs(noff[1][1]-noff[0][1]); // i==j for diamond fill const int slen = (i > j) ? i : j; @@ -328,13 +343,9 @@ RpictSimulManager::FillSquare(const int x, const int y // helper function to set up quincunx sampling static void -SetQuincunx(ABitMap2 *bmp2, int noff[4][2], const int spc, const bool odd) +SetQuincunx(ABitMap2 *bmp2, int noff[4][2], const int spc, bool odd, int x0, int y) { - for (int y = 0; y < bmp2->Height(); y += spc>>1) - for (int x = (odd^(y&1))*(spc>>1); x < bmp2->Width(); x += spc) - bmp2->Set(x, y); - // order neighbors CCW - if (odd) { + if (odd) { // order neighbors CCW noff[0][0] = spc>>1; noff[0][1] = 0; noff[1][0] = 0; noff[1][1] = spc>>1; noff[2][0] = -(spc>>1); noff[2][1] = 0; @@ -345,11 +356,27 @@ SetQuincunx(ABitMap2 *bmp2, int noff[4][2], const int noff[2][0] = -(spc>>1); noff[2][1] = -(spc>>1); noff[3][0] = spc>>1; noff[3][1] = -(spc>>1); } + int nsteps; // non-negative range + if (x0 < -(spc>>1)) { + nsteps = (spc-1 - x0 - (spc>>1))/spc; + x0 += nsteps*spc; + } + if (y < 0) { // get past y==0 + nsteps = ((spc>>1)-1 - y)/(spc>>1); + y += nsteps*(spc>>1); + odd ^= nsteps&1; + } + while (y < bmp2->Height()) { + for (int x = x0 + odd*(spc>>1); x < bmp2->Width(); x += spc) + bmp2->Set(x, y); + y += spc>>1; + odd = !odd; + } } // Render (or finish rendering) current tile bool -RpictSimulManager::RenderRect() +RpictSimulManager::RenderRect(const int x0, const int y0) { if (!tvw.type || !Ready()) { error(INTERNAL, "need octree and view for RenderRect()"); @@ -359,14 +386,12 @@ RpictSimulManager::RenderRect() int sp2 = ceil(log2((TWidth()>THeight() ? TWidth() : THeight()) - 1.)); int layer = 0; int x, y; -// fprintf(stderr, "Rendering %dx%d tile with psample=%d, maxdiff=%.3f ...\n", -// TWidth(), THeight(), psample, maxdiff); while (sp2 > 0) { ABitMap2 sampMap(TWidth(), THeight()); int noff[4][2]; if ((prCB != NULL) & (barPix == NULL)) (*prCB)(100.*doneMap.SumTotal()/doneMap.Width()/doneMap.Height()); - SetQuincunx(&sampMap, noff, 1< 0; ) { @@ -583,12 +601,11 @@ RpictSimulManager::RenderBelow(int ytop, const int vst } int lastOut = ytop; // render down frame while (ytop > 0) { -// fprintf(stderr, "At y=%d, source drawing %s...\n", ytop, parr ? "ON" : "OFF"); if (prCB) (*prCB)(100.*(GetHeight()-ytop)/GetHeight()); - if (!RenderRect()) // render this bar + if (!RenderRect(0, THeight()-ytop)) // render this bar return false; - int nlines = lastOut - ytop + THeight(); + int nlines = lastOut - ytop + vstep; if (nlines > ytop) nlines = ytop; else if (parr) // drawing sources? @@ -652,7 +669,7 @@ RpictSimulManager::NewOutput(FILE *pdfp[2], const char { pdfp[0] = pdfp[1] = NULL; if (!RDTcolorT(dt)) - error(INTERNAL, "botched color output type in NewOutput()"); + error(INTERNAL, "missing color output type in NewOutput()"); if (NCSAMP == 3) { if (RDTcolorT(dt) == RDTscolr) dt = RDTnewCT(dt, prims==xyzprims ? RDTxyze : RDTrgbe); @@ -667,23 +684,23 @@ RpictSimulManager::NewOutput(FILE *pdfp[2], const char error(INTERNAL, "writing picture to a command not supported"); return RDTnone; } - fd = open(pfname, O_WRONLY|O_CREAT|O_EXCL, 0666); + fd = open(pfname, O_RDWR|O_CREAT|O_EXCL, 0666); } if (fd < 0) { if ((frameNo <= 0) | (errno != EEXIST)) { sprintf(errmsg, "cannot open picture file '%s'", pfname); error(SYSTEM, errmsg); } - return RDTnone; // expected in parallel sequence + return RDTnone; // may be expected in sequence run } if (fd == 1) pdfp[0] = stdout; - else if (!(pdfp[0] = fdopen(fd, "w"))) + else if (!(pdfp[0] = fdopen(fd, "w+"))) error(SYSTEM, "failure calling fdopen()"); SET_FILE_BINARY(pdfp[0]); // write picture header if ((pdfp[0] != stdout) | (frameNo <= 1)) { newheader("RADIANCE", pdfp[0]); - fputs(GetHeader(), pdfp[0]); + fputs(GetHeadStr(), pdfp[0]); } fputs(VIEWSTR, pdfp[0]); fprintview(&vw, pdfp[0]); fputc('\n', pdfp[0]); if (frameNo > 0) @@ -729,10 +746,9 @@ RpictSimulManager::NewOutput(FILE *pdfp[2], const char fputendian(pdfp[0]); fputformat("float", pdfp[0]); break; - default:; + default:; // pro forma - caught this above } - fputc('\n', pdfp[0]); // flush picture header + resolution - fprtresolu(GetWidth(), GetHeight(), pdfp[0]); + fputc('\n', pdfp[0]); // flush picture header if (fflush(pdfp[0]) == EOF) { sprintf(errmsg, "cannot write header to picture '%s'", pfname); error(SYSTEM, errmsg); @@ -740,11 +756,11 @@ RpictSimulManager::NewOutput(FILE *pdfp[2], const char pdfp[0] = NULL; return RDTnone; } - if (dfname) { + if (dfname) { // open depth output if (dfname[0] == '!') pdfp[1] = popen(dfname+1, "w"); else - pdfp[1] = fopen(dfname, "w"); + pdfp[1] = fopen(dfname, "w+"); if (!pdfp[1]) { sprintf(errmsg, "cannot open depth output '%s'", dfname); error(SYSTEM, errmsg); @@ -756,12 +772,11 @@ RpictSimulManager::NewOutput(FILE *pdfp[2], const char } if (RDTdepthT(dt) == RDTdshort) { // write header for 16-bit depth? newheader("RADIANCE", pdfp[1]); - fputs(GetHeader(), pdfp[1]); + fputs(GetHeadStr(), pdfp[1]); fputs(VIEWSTR, pdfp[1]); fprintview(&vw, pdfp[1]); fputc('\n', pdfp[1]); fputs(DEPTHSTR, pdfp[1]); fputs(dunit, pdfp[1]); fputc('\n', pdfp[1]); fputformat(DEPTH16FMT, pdfp[1]); fputc('\n', pdfp[1]); // end-of-info - fprtresolu(GetWidth(), GetHeight(), pdfp[1]); if (fflush(pdfp[1]) == EOF) { sprintf(errmsg, "cannot write header to '%s'", dfname); error(SYSTEM, errmsg); @@ -788,15 +803,18 @@ RpictSimulManager::RenderFrame(const char *pfname, Ren dt = NewOutput(pdfp, pfname, dt, dfname); if (dt == RDTnone) return RDTnone; + // add resolution string(s) + fprtresolu(GetWidth(), GetHeight(), pdfp[0]); + if (RDTdepthT(dt) == RDTdshort) + fprtresolu(GetWidth(), GetHeight(), pdfp[1]); - const int bheight = (psample > 1) ? int(2*psample+.99) : 4; - const int vstep = bheight >> (psample > 1); + const int bheight = (psample > 1) ? int(8*psample+.99) : 16; + const int vstep = bheight >> (psample > 1); NewBar(bheight); // render frame if we can if (!RenderBelow(GetHeight(), vstep, pdfp[0], dt, pdfp[1])) { fclose(pdfp[0]); if (pdfp[1]) (dfname[0] == '!') ? pclose(pdfp[1]) : fclose(pdfp[1]); - Cleanup(); return RDTnone; } NewBar(); // clean up and return @@ -983,6 +1001,10 @@ RpictSimulManager::ReopenOutput(FILE *pdfp[2], const c pdfp[0] = NULL; return RDTnone; } + if (hinfo.gotview) { // header view overrides + pvw = vw; + vw = hinfo.vw; + } if (!dfname) // no depth file? return dt; @@ -1002,8 +1024,8 @@ RpictSimulManager::ReopenOutput(FILE *pdfp[2], const c } SET_FILE_BINARY(pdfp[1]); int n, len = strlen(HDRSTR); - char buf[32]; // sniff for 16-bit header - if (read(fileno(pdfp[1]), buf, len+1) < len+1) { + char buf[32]; // sniff for 16-bit header + if (getbinary(buf, 1, len+1, pdfp[1]) < len+1) { sprintf(errmsg, "empty depth file '%s'", dfname); error(SYSTEM, errmsg); fclose(pdfp[0]); fclose(pdfp[1]); @@ -1012,12 +1034,12 @@ RpictSimulManager::ReopenOutput(FILE *pdfp[2], const c } for (n = 0; n < len; n++) if (buf[n] != HDRSTR[n]) - break; // not a Radiance header - lseek(fileno(pdfp[1]), 0, SEEK_SET); + break; // not a Radiance header + rewind(pdfp[1]); if ((n < len) | !isprint(buf[len])) return RDTnewDT(dt, RDTdfloat); - HeaderInfo dinfo; // thinking it's 16-bit encoded + HeaderInfo dinfo; // thinking it's 16-bit encoded if (getheader(pdfp[1], head_check, &dinfo) < 0) sprintf(errmsg, "bad header in encoded depth file '%s'", dfname); @@ -1056,17 +1078,17 @@ RpictSimulManager::ResumeFrame(const char *pfname, con case RDTxyze: break; case RDTscolr: - bytesPer = hinfo.ncomp + 1; // XXX assumes no compression + bytesPer = NCSAMP + 1; // XXX assumes no compression break; case RDTrgb: case RDTxyz: bytesPer = sizeof(float)*3; break; case RDTscolor: - bytesPer = sizeof(float)*hinfo.ncomp; + bytesPer = sizeof(float)*NCSAMP; break; default: - sprintf(errmsg, "unknown format (%s) for '%s'", hinfo.fmt, pfname); + sprintf(errmsg, "unknown format for '%s'", pfname); error(USER, errmsg); fclose(pdfp[0]); if (pdfp[1]) fclose(pdfp[1]); @@ -1080,11 +1102,10 @@ RpictSimulManager::ResumeFrame(const char *pfname, con if (pdfp[1]) fclose(pdfp[1]); return RDTnone; } - vw.type = 0; // set up new (unreferenced) frame - frameNo = 0; + frameNo = 0; // set up unreferenced frame int hvdim[2] = {res.xr, res.yr}; double noAdj = 0; - if (!NewFrame(hinfo.vw, hvdim, &noAdj) || + if (!NewFrame(vw, hvdim, &noAdj) || (hvdim[0] != res.xr) | (hvdim[1] != res.yr)) { error(CONSISTENCY, "unexpected resolution change in ResumeFrame()"); fclose(pdfp[0]); @@ -1130,7 +1151,7 @@ RpictSimulManager::ResumeFrame(const char *pfname, con error(WARNING, errmsg); } long toSkip = 0; - switch (RDTdepthT(dt)) { // append depth file, too? + switch (RDTdepthT(dt)) { // append depth file, too? case RDTdfloat: toSkip = sizeof(float)*GetWidth()*doneScans; break; @@ -1145,14 +1166,14 @@ RpictSimulManager::ResumeFrame(const char *pfname, con toSkip = 2L*GetWidth()*doneScans; break; default:; - } - if (toSkip && fseek(pdfp[1], toSkip, SEEK_CUR) < 0) { + } // fseek() needed for output + if (pdfp[1] && fseek(pdfp[1], toSkip, SEEK_CUR) < 0) { sprintf(errmsg, "cannot seek on depth file '%s'", dfname); error(SYSTEM, errmsg); fclose(pdfp[0]); fclose(pdfp[1]); return RDTnone; } - int bheight = (psample > 1) ? int(2*psample+.99) : 4; + int bheight = (psample > 1) ? int(8*psample+.99) : 16; if (bheight > GetHeight()-doneScans) bheight = GetHeight()-doneScans; int vstep = bheight >> (psample > 1); @@ -1162,7 +1183,6 @@ RpictSimulManager::ResumeFrame(const char *pfname, con if (!RenderBelow(GetHeight()-doneScans, vstep, pdfp[0], dt, pdfp[1])) { fclose(pdfp[0]); if (pdfp[1]) fclose(pdfp[1]); - Cleanup(); return RDTnone; } NewBar(); // close up and return success