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, 3 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

# Content
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 */