ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/RpictSimulManager.h
Revision: 2.1
Committed: Wed Aug 14 20:05:23 2024 UTC (8 months, 2 weeks ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
feat(rxpict): Added new C++ picture rendering tool with multi-processing and spectral output

File Contents

# User Rev Content
1 greg 2.1 /* RCSid $Id$ */
2     /*
3     * RpictSimulManager.h
4     *
5     * Rpict simulation manager class declaration
6     *
7     * Created by Greg Ward on 07/11/2024.
8     */
9    
10     #ifndef RpictSimulManager_h
11     #define RpictSimulManager_h
12    
13     #include "RtraceSimulManager.h"
14     #include "view.h"
15     #include "depthcodec.h"
16     #include "abitmap.h"
17    
18     /// Data type flags for pixel access and output
19     enum RenderDataType {
20     RDTnone=0,
21     RDTscolor=0x1, RDTrgb=0x2, RDTxyz=0x3, RDTscolr=0x4, RDTrgbe=0x5, RDTxyze=0x6,
22     RDTcolorM=0x7,
23     RDTdfloat=0x8, RDTdshort=0x10,
24     RDTdepthM=0x18
25     };
26    
27     #define RDTcolorT(f) RenderDataType((f) & RDTcolorM)
28     #define RDTdepthT(f) RenderDataType((f) & RDTdepthM)
29     #define RDTcommonE(f) (RDTcolorT(f) >= RDTscolr)
30     #define RDTnewCT(f,c) RenderDataType((f) & ~RDTcolorM | (c))
31     #define RDTnewDT(f,d) RenderDataType((f) & ~RDTdepthM | (d))
32    
33     /// Pixel accessor (read/write to caller's buffer with possible conversion)
34     class PixelAccess {
35     union {
36     COLORV * f;
37     COLRV * b;
38     } pbase; // pixel base pointer
39     union {
40     float * f;
41     short * s;
42     } dbase; // depth base pointer
43     long rowStride; // # values to next y position
44     int dtyp; // data type flags
45     RGBPRIMP primp; // color primaries if tristimulus
46     COLORMAT xyz2myrgbmat; // custom color conversion matrix
47     COLORV * CF3(int x, int y) {
48     return pbase.f + (rowStride*y + x)*3;
49     }
50     COLORV * GetCF3(int x, int y) const {
51     return const_cast<COLORV *>(pbase.f + (rowStride*y + x)*3);
52     }
53     COLORV * SCF(int x, int y) {
54     return pbase.f + (rowStride*y + x)*NCSAMP;
55     }
56     COLORV * GetSCF(int x, int y) const {
57     return const_cast<COLORV *>(pbase.f + (rowStride*y + x)*NCSAMP);
58     }
59     COLRV * CB3(int x, int y) {
60     return pbase.b + (rowStride*y + x)*4;
61     }
62     COLRV * GetCB3(int x, int y) const {
63     return const_cast<COLRV *>(pbase.b + (rowStride*y + x)*4);
64     }
65     COLRV * SCB(int x, int y) {
66     return pbase.b + (rowStride*y + x)*(NCSAMP+1);
67     }
68     COLRV * GetSCB(int x, int y) const {
69     return const_cast<COLRV *>(pbase.b + (rowStride*y + x)*(NCSAMP+1));
70     }
71     public:
72     double refDepth; // reference depth
73     PixelAccess() {
74     refDepth = 1.;
75     Init();
76     }
77     PixelAccess(COLORV *rp, int ystride, float *zp=NULL) {
78     refDepth = 1.;
79     Init(rp, ystride, zp);
80     }
81     PixelAccess(COLRV *bp, int ystride, float *zp=NULL) {
82     refDepth = 1.;
83     Init(bp, ystride, zp);
84     }
85     PixelAccess(COLRV *bp, int ystride, short *dp) {
86     refDepth = 1.;
87     Init(bp, ystride, dp);
88     }
89     void Init() {
90     pbase.f = NULL; dbase.f = NULL;
91     rowStride = 0;
92     primp = NULL;
93     dtyp = 0;
94     }
95     /// Initializers default to rendering color space
96     void Init(COLORV *rp, int ystride, float *zp=NULL) {
97     pbase.f = rp; dbase.f = zp;
98     rowStride = ystride;
99     if (NCSAMP > 3) {
100     dtyp = RDTscolor; primp = NULL;
101     } else {
102     dtyp = RDTrgb; primp = stdprims;
103     }
104     if (zp) dtyp |= RDTdfloat;
105     }
106     void Init(COLRV *bp, int ystride, float *zp=NULL) {
107     pbase.b = bp; dbase.f = zp;
108     rowStride = ystride;
109     if (NCSAMP > 3) {
110     dtyp = RDTscolr; primp = NULL;
111     } else {
112     dtyp = RDTrgbe; primp = stdprims;
113     }
114     if (zp) dtyp |= RDTdfloat;
115     }
116     void Init(COLRV *bp, int ystride, short *dp) {
117     pbase.b = bp; dbase.s = dp;
118     rowStride = ystride;
119     if (NCSAMP > 3) {
120     dtyp = RDTscolr; primp = NULL;
121     } else {
122     dtyp = RDTrgbe; primp = stdprims;
123     }
124     if (dp) dtyp |= RDTdshort;
125     }
126     /// Set color space after non-empty initialization
127     bool SetColorSpace(RenderDataType cs, RGBPRIMP pr=NULL);
128     /// Get color space
129     RenderDataType ColorSpace() const {
130     return RDTcolorT(dtyp);
131     }
132     /// Get color primaries (NULL if spectral)
133     RGBPRIMP Primaries() const {
134     return primp;
135     }
136     /// Number of represented color/spectral components
137     int NC() const {
138     switch (ColorSpace()) {
139     case RDTrgb: case RDTrgbe:
140     case RDTxyz: case RDTxyze:
141     return 3;
142     case RDTscolor: case RDTscolr:
143     return NCSAMP;
144     default:;
145     }
146     return 0;
147     }
148     /// Get depth type
149     RenderDataType DepthType() const {
150     return RDTdepthT(dtyp);
151     }
152     /// Get row stride
153     long GetRowStride() const {
154     return rowStride;
155     }
156     /// Assign a pixel value (& depth) from rendered ray value
157     bool SetPixel(int x, int y, const RAY *rp);
158     /// Assign pixel color (& depth) -- may re-represent either/both
159     bool SetPixel(int x, int y, const COLORV *pv, float z=0) {
160     if (NC() == 3) {
161     if (RDTcommonE(dtyp))
162     setcolr(CB3(x,y), pv[RED], pv[GRN], pv[BLU]);
163     else
164     copycolor(CF3(x,y), pv);
165     } else if (RDTcommonE(dtyp))
166     scolor_scolr(SCB(x,y), pv);
167     else
168     copyscolor(SCF(x,y), pv);
169     if (RDTdepthT(dtyp) == RDTdfloat)
170     dbase.f[rowStride*y + x] = z;
171     else if (RDTdepthT(dtyp) == RDTdshort)
172     dbase.s[rowStride*y + x] = depth2code(z, refDepth);
173     return true;
174     }
175     /// Retrieve pixel color (& depth) -- may convert either/both
176     bool GetPixel(int x, int y, COLORV *pv, float *zp=NULL) const {
177     if (NC() == 3) {
178     if (RDTcommonE(dtyp))
179     colr_color(pv, GetCB3(x,y));
180     else
181     copycolor(pv, GetCF3(x,y));
182     } else if (RDTcommonE(dtyp))
183     scolr_scolor(pv, GetSCB(x,y));
184     else
185     copyscolor(pv, GetSCF(x,y));
186     if (!zp) return true;
187     if (RDTdepthT(dtyp) == RDTdfloat)
188     *zp = dbase.f[rowStride*y + x];
189     else if (RDTdepthT(dtyp) == RDTdshort)
190     *zp = code2depth(dbase.s[rowStride*y + x], refDepth);
191     else
192     *zp = .0f;
193     return true;
194     }
195     /// Copy pixel from one location to another (no conversion)
196     bool CopyPixel(int dx, int dy, int sx, int sy) {
197     if ((dx==sx) & (dy==sy)) return true;
198     const int nc = NC();
199     if (nc == 3) {
200     if (RDTcommonE(dtyp))
201     copycolr(CB3(dx,dy), GetCB3(sx,sy));
202     else
203     copycolor(CF3(dx,dy), GetCF3(sx,sy));
204     } else if (RDTcommonE(dtyp))
205     copyscolr(SCB(dx,dy), GetSCB(sx,sy));
206     else
207     copyscolor(SCF(dx,dy), GetSCF(sx,sy));
208     switch (RDTdepthT(dtyp)) {
209     case RDTdfloat:
210     dbase.f[rowStride*dy + dx] =
211     dbase.f[rowStride*sy + sx];
212     break;
213     case RDTdshort:
214     dbase.s[rowStride*dy + dx] =
215     dbase.s[rowStride*sy + sx];
216     break;
217     default:;
218     }
219     return true;
220     }
221     };
222    
223     /// Call-back function for progress reporting
224     typedef void ProgReportCB(double pct);
225    
226     /// rpict-like simulation manager (at most one such object)
227     class RpictSimulManager : protected RtraceSimulManager {
228     static RayReportCall RtCall; // our callback for cooked rays
229     VIEW vw; // frame view
230     VIEW pvw; // previous view
231     int hvres[2]; // overall picture dimensions
232     int tgsize[2]; // tile grid size
233     int thvres[2]; // tile dimensions
234     VIEW tvw, ptvw; // this tile's view (& previous)
235     PixelAccess pacc; // pixel accessor
236     char dunit[32]; // depth with units (if any)
237     ABitMap2 doneMap; // which tile pixels are done
238     COLORV * barPix; // current render bar pixels
239     float * barDepth; // current render bar depths
240     bool SetTile(const int ti[2]);
241     bool RenderRect();
242     bool ComputePixel(int x, int y);
243     bool BelowSampThresh(int x, int y, const int noff[4][2]) const;
244     void FillSquare(int x, int y, const int noff[4][2]);
245     void NewBar(int ht = 0);
246     bool LowerBar(int v);
247     bool RenderBelow(int ytop, const int vstep, FILE *pfp,
248     const int dt, FILE *dfp=NULL);
249     public:
250     ProgReportCB * prCB; // progress report call-back
251     RGBPRIMP prims; // output primaries (NULL if spectral)
252     int frameNo; // frame number (0 if not sequence)
253     RpictSimulManager(const char *octn = NULL) :
254     RtraceSimulManager(RtCall, this, octn) {
255     tvw.type = vw.type = 0;
256     hvres[0] = hvres[1] = 0;
257     thvres[0] = thvres[1] = 0;
258     pacc.refDepth = 1.; dunit[0] = '1'; dunit[1] = '\0';
259     barPix = NULL; barDepth = NULL;
260     prCB = NULL;
261     prims = NULL;
262     frameNo = 0;
263     }
264     ~RpictSimulManager() {
265     NewBar();
266     }
267     /// Load octree and prepare renderer
268     bool LoadOctree(const char *octn) {
269     return RtraceSimulManager::LoadOctree(octn);
270     }
271     /// Prepare header from previous input (or clear)
272     bool NewHeader(const char *inspec=NULL) {
273     return RtraceSimulManager::NewHeader(inspec);
274     }
275     /// Add a string to header (adds newline if none)
276     bool AddHeader(const char *str) {
277     return RtraceSimulManager::AddHeader(str);
278     }
279     /// Append program line to header
280     bool AddHeader(int ac, char *av[]) {
281     return RtraceSimulManager::AddHeader(ac, av);
282     }
283     /// Get header lines if any
284     const char * GetHeader() const {
285     return RtraceSimulManager::GetHeader();
286     }
287     /// Set number of computation threads (0 => #cores)
288     int SetThreadCount(int nt = 0) {
289     return RtraceSimulManager::SetThreadCount(nt);
290     }
291     /// Check thread count (1 means no multi-threading)
292     int NThreads() const {
293     return RtraceSimulManager::NThreads();
294     }
295     /// How many threads are currently unoccupied?
296     int ThreadsAvailable() const {
297     return RtraceSimulManager::ThreadsAvailable();
298     }
299     /// Are we ready?
300     bool Ready() const {
301     return RtraceSimulManager::Ready();
302     }
303     /// Assign reference depth string (e.g., "2.5/meter")
304     bool SetReferenceDepth(const char *dstr) {
305     double dref = atof(dstr);
306     if (dref <= .0) return false;
307     strlcpy(dunit, dstr, sizeof(dunit));
308     pacc.refDepth = dref;
309     return true;
310     }
311     bool SetReferenceDepth(double dref, const char *unit=NULL) {
312     if (dref <= .0) return false;
313     if (unit) sprintf(dunit, "%g/%s", dref, unit);
314     else sprintf(dunit, "%g", dref);
315     pacc.refDepth = dref;
316     return true;
317     }
318     /// Return reference depth
319     double GetReferenceDepth(char *du=NULL) const {
320     if (du) strcpy(du, dunit);
321     return pacc.refDepth;
322     }
323     /// Set up rendering frame (call after octree loaded)
324     /// Overall dimensions may be adjusted for view,
325     /// optional pixel aspect ratio and tile grid
326     /// Increments frameNo if >0
327     bool NewFrame(const VIEW &v, int xydim[2], double *ap=NULL,
328     const int *tgrid=NULL);
329     /// Get current picture width
330     int GetWidth() const {
331     return hvres[0];
332     }
333     /// Get current picture height
334     int GetHeight() const {
335     return hvres[1];
336     }
337     /// Tile width
338     int TWidth() const {
339     return thvres[0];
340     }
341     /// Tile height
342     int THeight() const {
343     return thvres[1];
344     }
345     /// Render the specified tile in frame
346     /// Tile pixels are contiguous unless ystride != 0
347     /// Tiles numbered from lower-left at (0,0)
348     /// Pixel type influenced by this->prims assignment
349     bool RenderTile(COLORV *rp, int ystride=0, float *zp=NULL,
350     const int *tile=NULL);
351     /// Same but store as common-exponent COLR or SCOLR
352     bool RenderTile(COLRV *bp, int ystride=0, float *zp=NULL,
353     const int *tile=NULL);
354     /// Same but also use 16-bit encoded depth buffer
355     bool RenderTile(COLRV *bp, int ystride, short *dp,
356     const int *tile=NULL);
357     /// Render and write a frame to the named file
358     /// Include any header lines set prior to call
359     /// Picture file must not already exist
360     /// Picture to stdout if pfname==NULL
361     /// Depth written to a command if dfname[0]=='!'
362     RenderDataType RenderFrame(const char *pfname,
363     RenderDataType dt=RDTrgbe,
364     const char *dfname=NULL);
365     /// Resume partially finished rendering
366     /// Picture file must exist with valid header
367     RenderDataType ResumeFrame(const char *pfname,
368     const char *dfname=NULL);
369     /// Close octree, free data, return status
370     int Cleanup(bool everything = false) {
371     NewBar();
372     tvw.type = vw.type = 0;
373     hvres[0] = hvres[1] = 0;
374     thvres[0] = thvres[1] = 0;
375     prims = NULL;
376     frameNo = 0;
377     return RtraceSimulManager::Cleanup(everything);
378     }
379     };
380    
381     #endif /* RpictSimulManager_h */