ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/RpictSimulManager.cpp
(Generate patch)

Comparing ray/src/rt/RpictSimulManager.cpp (file contents):
Revision 2.7 by greg, Thu Aug 22 00:44:02 2024 UTC vs.
Revision 2.13 by greg, Fri Jan 10 19:09:12 2025 UTC

# Line 9 | Line 9 | static const char RCSid[] = "$Id$";
9   *  Created by Greg Ward on 07/11/2024.
10   */
11  
12 + #define DEBUG   1       // XXX temporary!
13 +
14   #include <ctype.h>
15   #include "platform.h"
16   #include "RpictSimulManager.h"
# Line 103 | Line 105 | RpictSimulManager::NewFrame(const VIEW &v, int xydim[2
105  
106          if (!xydim) return false;
107          if (!ap) ap = &pasp;
108 <        pvw = vw;                       // save previous view for motion blur
109 <        vw = v;
108 >        if (&v == &vw) {
109 >                pvw.type = 0;
110 >        } else {
111 >                pvw = vw;               // save previous view for motion blur
112 >                vw = v;
113 >        }
114          const char *    verr = setview(&vw);
115          if (verr) {
116                  error(WARNING, verr);
# Line 196 | Line 202 | RpictSimulManager::SetTile(const int ti[2])
202   bool
203   RpictSimulManager::ComputePixel(int x, int y)
204   {
205 <        static const SCOLOR     scBlack = {0};
205 >        DCHECK(doneMap.OffBitMap(x,y),
206 >                        CONSISTENCY, "illegal pixel index in ComputPixel()");
207          int     i;
208          FVECT   rodir[2];
209          double  hpos = (x+pixjitter())/TWidth();
210          double  vpos = (y+pixjitter())/THeight();
211          double  dlim = viewray(rodir[0], rodir[1], &tvw, hpos, vpos);
212          if (dlim < -FTINY) {    // off view?
213 <                pacc.SetPixel(x, y, scBlack);
213 >                pacc.SetPixel(x, y, scblack);
214                  doneMap.Set(x, y);
215                  return true;
216          }
# Line 233 | Line 240 | RpictSimulManager::ComputePixel(int x, int y)
240  
241   // Check if neighbor differences are below pixel sampling threshold
242   bool
243 < RpictSimulManager::BelowSampThresh(int x, int y, const int noff[4][2]) const
243 > RpictSimulManager::BelowSampThresh(const int x, const int y, const int noff[4][2]) const
244   {
245          SCOLOR  pval[4];
246          float   dist[4];
247          int     i, j;
248  
249          for (i = 4; i--; ) {            // get pixels from tile store
250 <                int     px = x + noff[i][0];
251 <                int     py = y + noff[i][1];
250 >                const int       px = x + noff[i][0];
251 >                const int       py = y + noff[i][1];
252                  if (!doneMap.Check(px, py) ||
253                                  !pacc.GetPixel(px, py, pval[i], &dist[i]))
254                          return false;
255          }
256 <        const bool      spectr = (pacc.NC() > 3);
257 <        for (i = 4; --i; )              // do pairwise comparisons
258 <            for (j = i; j--; ) {
259 <                if (pacc.DepthType() &&
253 <                                (dist[i] - dist[j] > maxdiff*dist[j]) |
256 >                                        // do pairwise comparisons
257 >        for (i = (pacc.DepthType() != RDTnone)*4; --i > 0; )
258 >            for (j = i; j--; )
259 >                if ((dist[i] - dist[j] > maxdiff*dist[j]) |
260                                  (dist[j] - dist[i] > maxdiff*dist[i]))
261                          return false;
262 <                if (spectr ? sbigsdiff(pval[i], pval[j], maxdiff) :
263 <                                bigdiff(pval[i], pval[j], maxdiff))
262 >        if (pacc.NC() > 3) {
263 >            for (i = 4; --i; )
264 >                for (j = i; j--; )
265 >                    if (sbigsdiff(pval[i], pval[j], maxdiff))
266                          return false;
267 <            }
268 <        return true;                    // linear interpolation OK
267 >        } else {
268 >            for (i = 4; --i; )
269 >                for (j = i; j--; )
270 >                    if (bigdiff(pval[i], pval[j], maxdiff))
271 >                        return false;
272 >        }
273 >        return true;
274   }
275  
276   // Fill an interior square patch with interpolated values
# Line 268 | Line 281 | RpictSimulManager::FillSquare(const int x, const int y
281          float   dist[4];
282          int     i, j;
283                                          // assumes 4 corners are valid!
284 <        for (i = 4; i--; )
284 >        for (i = 4; i--; ) {
285 >                DCHECK(!doneMap.Check(x+noff[i][0], y+noff[i][1]),
286 >                        CONSISTENCY, "inclusion of bad pixel in FillSquare()");
287                  pacc.GetPixel(x+noff[i][0], y+noff[i][1], pval[i], &dist[i]);
288 <
288 >        }
289          i = abs(noff[1][0]-noff[0][0]);
290          j = abs(noff[1][1]-noff[0][1]); // i==j for diamond fill
291          const int       slen =  (i > j) ? i : j;
# Line 328 | Line 343 | RpictSimulManager::FillSquare(const int x, const int y
343  
344   // helper function to set up quincunx sampling
345   static void
346 < SetQuincunx(ABitMap2 *bmp2, int noff[4][2], const int spc, const bool odd)
346 > SetQuincunx(ABitMap2 *bmp2, int noff[4][2], const int spc, bool odd, int x0, int y)
347   {
348 <        for (int y = 0; y < bmp2->Height(); y += spc>>1)
334 <            for (int x = (odd^(y&1))*(spc>>1); x < bmp2->Width(); x += spc)
335 <                bmp2->Set(x, y);
336 <                                        // order neighbors CCW
337 <        if (odd) {
348 >        if (odd) {                      // order neighbors CCW
349                  noff[0][0] = spc>>1; noff[0][1] = 0;
350                  noff[1][0] = 0; noff[1][1] = spc>>1;
351                  noff[2][0] = -(spc>>1); noff[2][1] = 0;
# Line 345 | Line 356 | SetQuincunx(ABitMap2 *bmp2, int noff[4][2], const int
356                  noff[2][0] = -(spc>>1); noff[2][1] = -(spc>>1);
357                  noff[3][0] = spc>>1; noff[3][1] = -(spc>>1);
358          }
359 +        int     nsteps;                 // non-negative range
360 +        if (x0 < -(spc>>1)) {
361 +                nsteps = (spc-1 - x0 - (spc>>1))/spc;
362 +                x0 += nsteps*spc;
363 +        }
364 +        if (y < 0) {                    // get past y==0
365 +                nsteps = ((spc>>1)-1 - y)/(spc>>1);
366 +                y += nsteps*(spc>>1);
367 +                odd ^= nsteps&1;
368 +        }
369 +        while (y < bmp2->Height()) {
370 +            for (int x = x0 + odd*(spc>>1); x < bmp2->Width(); x += spc)
371 +                bmp2->Set(x, y);
372 +            y += spc>>1;
373 +            odd = !odd;
374 +        }
375   }
376  
377   // Render (or finish rendering) current tile
378   bool
379 < RpictSimulManager::RenderRect()
379 > RpictSimulManager::RenderRect(const int x0, const int y0)
380   {
381          if (!tvw.type || !Ready()) {
382                  error(INTERNAL, "need octree and view for RenderRect()");
# Line 359 | Line 386 | RpictSimulManager::RenderRect()
386          int             sp2 = ceil(log2((TWidth()>THeight() ? TWidth() : THeight()) - 1.));
387          int             layer = 0;
388          int             x, y;
362 // fprintf(stderr, "Rendering %dx%d tile with psample=%d, maxdiff=%.3f ...\n",
363 // TWidth(), THeight(), psample, maxdiff);
389          while (sp2 > 0) {
390                  ABitMap2        sampMap(TWidth(), THeight());
391                  int             noff[4][2];
392                  if ((prCB != NULL) & (barPix == NULL))
393                          (*prCB)(100.*doneMap.SumTotal()/doneMap.Width()/doneMap.Height());
394 <                SetQuincunx(&sampMap, noff, 1<<sp2, layer&1);
394 >                SetQuincunx(&sampMap, noff, 1<<sp2, layer&1, x0, y0);
395                  sampMap -= doneSamples; // avoid resampling pixels
396                  // Are we into adaptive sampling realm?
397                  if (noff[0][0]*noff[0][0] + noff[0][1]*noff[0][1] < psample*psample) {
# Line 380 | Line 405 | RpictSimulManager::RenderRect()
405                          const ABitMap2  origSampMap = sampMap;
406                          for (x = 4; x--; ) {
407                                  ABitMap2        stamp = origSampMap;
408 <                                stamp.Shift(noff[x][0], noff[x][1]);
408 >                                stamp.Shift(noff[x][0] + noff[(x+1)&3][0],
409 >                                                noff[x][1] + noff[(x+1)&3][1]);
410                                  sampMap |= stamp;
411                          }               // ...but don't resample what's done
412                          sampMap -= doneSamples;
413                                          // interpolate smooth regions
414                          fillMap -= sampMap;
415 +                        fillMap -= doneSamples;
416                          for (x = y = 0; fillMap.Find(&x, &y); x++)
417                                  FillSquare(x, y, noff);
418                          doneSamples |= doneMap;
419                  }                       // compute required ray samples
420                  for (x = y = 0; sampMap.Find(&x, &y); x++)
421 <                        if (!ComputePixel(x, y))
421 >                        if (!ComputePixel(x, y)) {
422 >                                sprintf(errmsg, "ComputePixel(%d,%d) failed", x, y);
423 >                                error(WARNING, errmsg);
424                                  return false;
425 +                        }
426                  doneSamples |= sampMap; // samples now done or at least queued
397 // fprintf(stderr, "Sampled %ld pixels at (sp2,layer)=(%d,%d)\n",
398 // (long)sampMap.SumTotal(), sp2, layer);
399 // fprintf(stderr, "\t%ld pixels (%.3f%%) completed (+%ld in process)\n",
400 // (long)doneMap.SumTotal(), 100.*doneMap.SumTotal()/doneMap.Width()/doneMap.Height(),
401 // (long)(doneSamples.SumTotal()-doneMap.SumTotal()));
427                  sp2 -= layer++ & 1;     // next denser sampling
428          }
429          if (FlushQueue() < 0)           // make sure we got everyone
430                  return false;
431          x = y = 0;
432          if (doneMap.Find(&x, &y, false)) {
433 <                sprintf(errmsg, "missed %ld tile pixels, e.g. (%d,%d)",
434 <                                (long)doneMap.Width()*doneMap.Height() -
435 <                                        doneMap.SumTotal(), x, y);
433 >                sprintf(errmsg, "missed %.4f%% of pixels in rectangle\n",
434 >                                100. - 100.*doneMap.SumTotal() /
435 >                                        doneMap.Width() / doneMap.Height());
436                  error(WARNING, errmsg);
437          }
438          if ((prCB != NULL) & (barPix == NULL))
# Line 433 | Line 458 | RpictSimulManager::RenderTile(COLORV *rp, int ystride,
458                  pacc.SetColorSpace(RDTxyz);
459          else if (prims)
460                  pacc.SetColorSpace(RDTrgb, prims);
461 <                
461 >
462          return SetTile(tile) && RenderRect();
463   }
464  
# Line 537 | Line 562 | RpictSimulManager::LowerBar(int v, int ytop)
562                          sizeof(COLORV)*NC*TWidth()*(THeight()-v));
563          memmove(barDepth, barDepth + TWidth()*v,
564                          sizeof(float)*TWidth()*(THeight()-v));
565 <        if (ytop < THeight()) {                 // mark what we won't do as finished
565 >        if (ytop < THeight())                   // mark what we won't do as finished
566                  doneMap.ClearRect(0, 0, TWidth(), THeight()-ytop, true);
542                memset(barPix, 0, sizeof(COLORV)*NC*TWidth()*(THeight()-ytop));
543                memset(barDepth, 0, sizeof(float)*TWidth()*(THeight()-ytop));
544        }
567          return true;
568   }
569  
# Line 564 | Line 586 | RpictSimulManager::RenderBelow(int ytop, const int vst
586                          cropview(&ptvw, 0., double(ytop-THeight())/GetHeight(),
587                                                  1., double(ytop)/GetHeight()))
588                  ptvw.type = 0;
589 <                                                // set up spectral sampling
590 <        if (setspectrsamp(CNDX, WLPART) <= 0) {
589 >                                                // update spectral sampling
590 >        int     rv = setspectrsamp(CNDX, WLPART);
591 >        if (rv < 0) {
592                  error(USER, "unsupported spectral sampling");
593                  return false;
594          }
595 +        if (!rv & (RDTcolorT(dt) != RDTscolor) & (RDTcolorT(dt) != RDTscolr))
596 +                error(WARNING, "spectral range incompatible with color output");
597          COLORV **       parr = NULL;            // set up tiny source drawing
598          float **        zarr = NULL;
599          if (!ptvw.type && directvis && dblur <= FTINY) {
# Line 583 | Line 608 | RpictSimulManager::RenderBelow(int ytop, const int vst
608          }
609          int             lastOut = ytop;         // render down frame
610          while (ytop > 0) {
586 // fprintf(stderr, "At y=%d, source drawing %s...\n", ytop, parr ? "ON" : "OFF");
611                  if (prCB)
612                          (*prCB)(100.*(GetHeight()-ytop)/GetHeight());
613 <                if (!RenderRect())              // render this bar
613 >                if (!RenderRect(0, THeight()-ytop))     // render this bar
614                          return false;
615                  int     nlines = lastOut - ytop + THeight();
616                  if (nlines > ytop)
# Line 652 | Line 676 | RpictSimulManager::NewOutput(FILE *pdfp[2], const char
676   {
677          pdfp[0] = pdfp[1] = NULL;
678          if (!RDTcolorT(dt))
679 <                error(INTERNAL, "botched color output type in NewOutput()");
679 >                error(INTERNAL, "missing color output type in NewOutput()");
680          if (NCSAMP == 3) {
681                  if (RDTcolorT(dt) == RDTscolr)
682                          dt = RDTnewCT(dt, prims==xyzprims ? RDTxyze : RDTrgbe);
# Line 667 | Line 691 | RpictSimulManager::NewOutput(FILE *pdfp[2], const char
691                          error(INTERNAL, "writing picture to a command not supported");
692                          return RDTnone;
693                  }
694 <                fd = open(pfname, O_WRONLY|O_CREAT|O_EXCL, 0666);
694 >                fd = open(pfname, O_RDWR|O_CREAT|O_EXCL, 0666);
695          }
696          if (fd < 0) {
697                  if ((frameNo <= 0) | (errno != EEXIST)) {
698                          sprintf(errmsg, "cannot open picture file '%s'", pfname);
699                          error(SYSTEM, errmsg);
700                  }
701 <                return RDTnone;                 // expected in parallel sequence
701 >                return RDTnone;                 // may be expected in sequence run
702          }
703          if (fd == 1)
704                  pdfp[0] = stdout;
705 <        else if (!(pdfp[0] = fdopen(fd, "w")))
705 >        else if (!(pdfp[0] = fdopen(fd, "w+")))
706                  error(SYSTEM, "failure calling fdopen()");
707          SET_FILE_BINARY(pdfp[0]);               // write picture header
708          if ((pdfp[0] != stdout) | (frameNo <= 1)) {
709                  newheader("RADIANCE", pdfp[0]);
710 <                fputs(GetHeader(), pdfp[0]);
710 >                fputs(GetHeadStr(), pdfp[0]);
711          }
712          fputs(VIEWSTR, pdfp[0]); fprintview(&vw, pdfp[0]); fputc('\n', pdfp[0]);
713          if (frameNo > 0)
# Line 729 | Line 753 | RpictSimulManager::NewOutput(FILE *pdfp[2], const char
753                  fputendian(pdfp[0]);
754                  fputformat("float", pdfp[0]);
755                  break;
756 <        default:;
756 >        default:;       // pro forma - caught this above
757          }
758 <        fputc('\n', pdfp[0]);                   // flush picture header + resolution
758 >        fputc('\n', pdfp[0]);                   // flush picture header
759          if (fflush(pdfp[0]) == EOF) {
760                  sprintf(errmsg, "cannot write header to picture '%s'", pfname);
761                  error(SYSTEM, errmsg);
# Line 743 | Line 767 | RpictSimulManager::NewOutput(FILE *pdfp[2], const char
767                  if (dfname[0] == '!')
768                          pdfp[1] = popen(dfname+1, "w");
769                  else
770 <                        pdfp[1] = fopen(dfname, "w");
770 >                        pdfp[1] = fopen(dfname, "w+");
771                  if (!pdfp[1]) {
772                          sprintf(errmsg, "cannot open depth output '%s'", dfname);
773                          error(SYSTEM, errmsg);
# Line 755 | Line 779 | RpictSimulManager::NewOutput(FILE *pdfp[2], const char
779          }
780          if (RDTdepthT(dt) == RDTdshort) {       // write header for 16-bit depth?
781                  newheader("RADIANCE", pdfp[1]);
782 <                fputs(GetHeader(), pdfp[1]);
782 >                fputs(GetHeadStr(), pdfp[1]);
783                  fputs(VIEWSTR, pdfp[1]); fprintview(&vw, pdfp[1]); fputc('\n', pdfp[1]);
784                  fputs(DEPTHSTR, pdfp[1]); fputs(dunit, pdfp[1]); fputc('\n', pdfp[1]);
785                  fputformat(DEPTH16FMT, pdfp[1]);
# Line 791 | Line 815 | RpictSimulManager::RenderFrame(const char *pfname, Ren
815          if (RDTdepthT(dt) == RDTdshort)
816                  fprtresolu(GetWidth(), GetHeight(), pdfp[1]);
817  
818 <        const int       bheight = (psample > 1) ? int(2*psample+.99) : 4;
819 <        const int       vstep =  bheight >> (psample > 1);
818 >        const int       bheight = (psample > 1) ? int(8*psample+.99) : 16;
819 >        const int       vstep = bheight >> (psample > 1);
820  
821          NewBar(bheight);                        // render frame if we can
822          if (!RenderBelow(GetHeight(), vstep, pdfp[0], dt, pdfp[1])) {
823                  fclose(pdfp[0]);
824                  if (pdfp[1]) (dfname[0] == '!') ? pclose(pdfp[1]) : fclose(pdfp[1]);
801                Cleanup();
825                  return RDTnone;
826          }
827          NewBar();                               // clean up and return
# Line 985 | Line 1008 | RpictSimulManager::ReopenOutput(FILE *pdfp[2], const c
1008                  pdfp[0] = NULL;
1009                  return RDTnone;
1010          }
1011 +        if (hinfo.gotview) {                    // header view overrides
1012 +                pvw = vw;
1013 +                vw = hinfo.vw;
1014 +        }
1015          if (!dfname)                            // no depth file?
1016                  return dt;
1017  
# Line 1004 | Line 1031 | RpictSimulManager::ReopenOutput(FILE *pdfp[2], const c
1031          }
1032          SET_FILE_BINARY(pdfp[1]);
1033          int     n, len = strlen(HDRSTR);
1034 <        char    buf[32];                // sniff for 16-bit header
1034 >        char    buf[32];                        // sniff for 16-bit header
1035          if (getbinary(buf, 1, len+1, pdfp[1]) < len+1) {
1036                  sprintf(errmsg, "empty depth file '%s'", dfname);
1037                  error(SYSTEM, errmsg);
# Line 1014 | Line 1041 | RpictSimulManager::ReopenOutput(FILE *pdfp[2], const c
1041          }
1042          for (n = 0; n < len; n++)
1043                  if (buf[n] != HDRSTR[n])
1044 <                        break;          // not a Radiance header
1044 >                        break;                  // not a Radiance header
1045          rewind(pdfp[1]);
1046          if ((n < len) | !isprint(buf[len]))
1047                  return RDTnewDT(dt, RDTdfloat);
1048  
1049 <        HeaderInfo      dinfo;          // thinking it's 16-bit encoded
1049 >        HeaderInfo      dinfo;                  // thinking it's 16-bit encoded
1050          if (getheader(pdfp[1], head_check, &dinfo) < 0)
1051                  sprintf(errmsg, "bad header in encoded depth file '%s'",
1052                                  dfname);
# Line 1058 | Line 1085 | RpictSimulManager::ResumeFrame(const char *pfname, con
1085          case RDTxyze:
1086                  break;
1087          case RDTscolr:
1088 <                bytesPer = hinfo.ncomp + 1;     // XXX assumes no compression
1088 >                bytesPer = NCSAMP + 1;  // XXX assumes no compression
1089                  break;
1090          case RDTrgb:
1091          case RDTxyz:
1092                  bytesPer = sizeof(float)*3;
1093                  break;
1094          case RDTscolor:
1095 <                bytesPer = sizeof(float)*hinfo.ncomp;
1095 >                bytesPer = sizeof(float)*NCSAMP;
1096                  break;
1097          default:
1098 <                sprintf(errmsg, "unknown format (%s) for '%s'", hinfo.fmt, pfname);
1098 >                sprintf(errmsg, "unknown format for '%s'", pfname);
1099                  error(USER, errmsg);
1100                  fclose(pdfp[0]);
1101                  if (pdfp[1]) fclose(pdfp[1]);
# Line 1082 | Line 1109 | RpictSimulManager::ResumeFrame(const char *pfname, con
1109                  if (pdfp[1]) fclose(pdfp[1]);
1110                  return RDTnone;
1111          }
1112 <        vw.type = 0;                            // set up new (unreferenced) frame
1086 <        frameNo = 0;
1112 >        frameNo = 0;                            // set up unreferenced frame
1113          int     hvdim[2] = {res.xr, res.yr};
1114          double  noAdj = 0;
1115 <        if (!NewFrame(hinfo.vw, hvdim, &noAdj) ||
1115 >        if (!NewFrame(vw, hvdim, &noAdj) ||
1116                          (hvdim[0] != res.xr) | (hvdim[1] != res.yr)) {
1117                  error(CONSISTENCY, "unexpected resolution change in ResumeFrame()");
1118                  fclose(pdfp[0]);
# Line 1154 | Line 1180 | RpictSimulManager::ResumeFrame(const char *pfname, con
1180                  fclose(pdfp[0]); fclose(pdfp[1]);
1181                  return RDTnone;
1182          }
1183 <        int     bheight = (psample > 1) ? int(2*psample+.99) : 4;
1183 >        int     bheight = (psample > 1) ? int(8*psample+.99) : 16;
1184          if (bheight > GetHeight()-doneScans)
1185                  bheight = GetHeight()-doneScans;
1186          int     vstep =  bheight >> (psample > 1);
# Line 1164 | Line 1190 | RpictSimulManager::ResumeFrame(const char *pfname, con
1190          if (!RenderBelow(GetHeight()-doneScans, vstep, pdfp[0], dt, pdfp[1])) {
1191                  fclose(pdfp[0]);
1192                  if (pdfp[1]) fclose(pdfp[1]);
1167                Cleanup();
1193                  return RDTnone;
1194          }
1195          NewBar();                               // close up and return success

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines