ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/RpictSimulManager.h
Revision: 2.9
Committed: Mon Sep 16 23:49:13 2024 UTC (7 months, 2 weeks ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.8: +25 -9 lines
Log Message:
feat(rxpiece): Initial working version of rxpiece C++ tiling renderer

File Contents

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