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

# User Rev Content
1 greg 2.11 /* RCSid $Id: RpictSimulManager.h,v 2.10 2024/10/10 21:02:52 greg Exp $ */
2 greg 2.1 /*
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 greg 2.2 #define RDTnewCT(f,c) RenderDataType((f) & ~RDTcolorM | (c) & RDTcolorM)
30     #define RDTnewDT(f,d) RenderDataType((f) & ~RDTdepthM | (d) & RDTdepthM)
31 greg 2.1
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 greg 2.9 bool swap2d; // need to swap 16-bit depths?
46 greg 2.2 const COLORV * CF3(int x, int y) const {
47     return pbase.f + (rowStride*y + x)*3;
48     }
49 greg 2.1 COLORV * CF3(int x, int y) {
50     return pbase.f + (rowStride*y + x)*3;
51     }
52 greg 2.2 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 greg 2.1 }
61     COLORV * SCF(int x, int y) {
62     return pbase.f + (rowStride*y + x)*NCSAMP;
63     }
64 greg 2.2 const COLRV * SCB(int x, int y) const {
65     return pbase.b + (rowStride*y + x)*(NCSAMP+1);
66 greg 2.1 }
67     COLRV * SCB(int x, int y) {
68     return pbase.b + (rowStride*y + x)*(NCSAMP+1);
69     }
70 greg 2.9 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 greg 2.1 public:
81     double refDepth; // reference depth
82     PixelAccess() {
83     refDepth = 1.;
84 greg 2.9 swap2d = !nativebigendian();
85 greg 2.1 Init();
86     }
87     PixelAccess(COLORV *rp, int ystride, float *zp=NULL) {
88     refDepth = 1.;
89 greg 2.9 swap2d = !nativebigendian();
90 greg 2.1 Init(rp, ystride, zp);
91     }
92     PixelAccess(COLRV *bp, int ystride, float *zp=NULL) {
93     refDepth = 1.;
94 greg 2.9 swap2d = !nativebigendian();
95 greg 2.1 Init(bp, ystride, zp);
96     }
97     PixelAccess(COLRV *bp, int ystride, short *dp) {
98     refDepth = 1.;
99 greg 2.9 swap2d = !nativebigendian();
100 greg 2.1 Init(bp, ystride, dp);
101     }
102 greg 2.4 PixelAccess(COLORV *rp, int ystride, short *dp) {
103     refDepth = 1.;
104 greg 2.9 swap2d = !nativebigendian();
105 greg 2.4 Init(rp, ystride, dp);
106     }
107 greg 2.1 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 greg 2.4 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 greg 2.1 /// 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 greg 2.9 if (DepthType() == RDTdfloat)
198 greg 2.1 dbase.f[rowStride*y + x] = z;
199 greg 2.9 else if (DepthType() == RDTdshort)
200     EncodeDepth16(x, y, z);
201 greg 2.1 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 greg 2.2 colr_color(pv, CB3(x,y));
208 greg 2.1 else
209 greg 2.2 copycolor(pv, CF3(x,y));
210 greg 2.1 } else if (RDTcommonE(dtyp))
211 greg 2.2 scolr_scolor(pv, SCB(x,y));
212 greg 2.1 else
213 greg 2.2 copyscolor(pv, SCF(x,y));
214 greg 2.1 if (!zp) return true;
215 greg 2.9 if (DepthType() == RDTdfloat)
216 greg 2.1 *zp = dbase.f[rowStride*y + x];
217 greg 2.9 else if (DepthType() == RDTdshort)
218     *zp = DecodeDepth16(x, y);
219 greg 2.1 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 greg 2.2 copycolr(CB3(dx,dy), CB3(sx,sy));
230 greg 2.1 else
231 greg 2.2 copycolor(CF3(dx,dy), CF3(sx,sy));
232 greg 2.1 } else if (RDTcommonE(dtyp))
233 greg 2.2 copyscolr(SCB(dx,dy), SCB(sx,sy));
234 greg 2.1 else
235 greg 2.2 copyscolor(SCF(dx,dy), SCF(sx,sy));
236 greg 2.9 switch (DepthType()) {
237 greg 2.1 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 greg 2.7 bool RenderRect(const int x0 = 0, const int y0 = 0);
270 greg 2.1 bool ComputePixel(int x, int y);
271 greg 2.7 bool BelowSampThresh(const int x, const int y,
272     const int noff[4][2]) const;
273 greg 2.2 void FillSquare(const int x, const int y, const int noff[4][2]);
274 greg 2.1 void NewBar(int ht = 0);
275 greg 2.3 bool LowerBar(int v, int ytop);
276 greg 2.1 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 greg 2.5 delete [] barPix; delete [] barDepth;
295 greg 2.1 }
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 greg 2.11 /// Get current header length in bytes
313     int GetHeadLen() const {
314     return RtraceSimulManager::GetHeadLen();
315     }
316 greg 2.1 /// Get header lines if any
317 greg 2.8 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 greg 2.1 }
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 greg 2.4 /// 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 greg 2.1 /// 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 greg 2.4 /// Back to float color with 16-bit depth
404     bool RenderTile(COLORV *rp, int ystride, short *dp,
405     const int *tile=NULL);
406 greg 2.1 /// Render and write a frame to the named file
407     /// Include any header lines set prior to call
408 greg 2.5 /// Picture file must not exist
409 greg 2.2 /// Write pixels to stdout if !pfname
410     /// Write depth to a command if dfname[0]=='!'
411 greg 2.1 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 greg 2.5 /// Prepare new picture (and depth) output
419 greg 2.9 /// Called by RenderFrame() after NewFrame()
420 greg 2.5 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 greg 2.6 /// Called by ResumeFrame()
425 greg 2.5 /// File pointers @ end of header (before res.)
426     RenderDataType ReopenOutput(FILE *pdfp[2], const char *pfname,
427     const char *dfname=NULL);
428 greg 2.1 /// 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 */