ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/RpictSimulManager.h
Revision: 2.11
Committed: Wed Oct 23 23:40:41 2024 UTC (6 months, 1 week ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.10: +5 -1 lines
Log Message:
feat: Added GetHeadLen() method for efficiency

File Contents

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