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

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