HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
IMG_DeepShadow.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: IMG_DeepShadow.h ( IMG Library, C++)
7  *
8  * COMMENTS: Deep shadow API
9  */
10 
11 #pragma once
12 
13 #ifndef __IMG_DeepShadow__
14 #define __IMG_DeepShadow__
15 
16 #include "IMG_API.h"
17 #include "IMG_DeepStat.h"
18 #include "IMG_FileTypes.h"
19 
20 #include <UT/UT_Rect.h>
21 #include <UT/UT_SharedPtr.h>
22 #include <UT/UT_UniquePtr.h>
23 #include <UT/UT_VectorTypes.h>
24 #include <UT/UT_ValArray.h>
25 #include <UT/UT_StringHolder.h>
26 #include <PXL/PXL_Forward.h>
27 
28 class PXL_DeepPixel;
29 class PXL_DeepSampleList;
30 class img_DeepShadow;
31 class IMG_DeepShadow;
33 class IMG_FileParms;
34 class IMG_Format;
35 class IMG_Stat;
36 class UT_WorkBuffer;
37 class UT_Options;
38 
39 /// @brief Thread-safe convenience class to make reading DSM pixels easy
40 ///
41 /// This is a thread-safe convenience class to wrap around reading pixels
42 /// which ensures that the pixel is closed properly.
43 ///
44 /// @warning Beware when declaring an IMG_DeepPixelReader in the same scope
45 /// as an IMG_DeepShadow. Since the pixel reader keeps a reference to the
46 /// file, the destruction order is important -- though calling close()
47 /// should avoid any problems.
48 ///
49 /// The class should be used as follows: @code
50 ///
51 /// IMG_DeepPixelReader pixel(dsm);
52 /// for (x, y) in raster {
53 /// if (pixel.open(x, y)) {
54 /// for (int i = 0; i < pixel.getDepth(); i++)
55 /// data = pixel.getData(chp, i);
56 /// }
57 /// }
58 /// @endcode
59 ///
61 {
62 public:
65 
66  /// Open a pixel for reading
67  bool open(int x, int y);
68  /// Close the pixel. This is called automatically on destruction.
69  /// However, if an IMG_DeepPixelReader and IMG_DeepShadow are created in
70  /// the same scope, the IMG_DeepPixelReader may hold onto references (and
71  /// cause crashing errors). Calling close() manually is a safe thing to
72  /// do.
73  void close();
74  /// Returns the number of z-records
75  int getDepth() const;
76  /// Return the data for the channel at the given depth index.
77  const float *getData(const IMG_DeepShadowChannel &chp,
78  int depth_index);
79 
80  /// Alternately, just fill a PXL_DeepSampleList with the appropriate
81  /// data. This manages zback, coverage, flags and other special deep
82  /// channels.
83  bool readPixel(int x, int y, PXL_DeepSampleList &pixel) const;
84 
85 
86  /// After opening, you can call either of these methods to ensure that the
87  /// data is in the correct form for your application. "composited" pixels
88  /// will have the data accumulated over from front to back. "uncomposited"
89  /// pixels will have the raw data for each z-record.
90  ///
91  /// If the force flag is false, then the state of the file will be used
92  /// to determine whether the deep records need to be processed or not.
93  ///
94  /// These methods should be called after the pixel has been opened.
95  void composite(const IMG_DeepShadowChannel &pz,
96  const IMG_DeepShadowChannel &of,
97  bool force = false);
98  void uncomposite(const IMG_DeepShadowChannel &pz,
99  const IMG_DeepShadowChannel &of,
100  bool force = false);
101 
102 private:
103  class DeepShadowPixel; // Forward declaration
104  DeepShadowPixel *myHandle;
105 };
106 
107 /// @brief Thread-safe convenience class to make writing DSM pixels easy
108 ///
109 /// This is a thread-safe convenience class to wrap around writing pixels
110 /// which ensures that the pixel is closed properly.
111 ///
112 /// @warning Beware when declaring an IMG_DeepPixelReader in the same scope
113 /// as an IMG_DeepShadow. Since the pixel reader keeps a reference to the
114 /// file, the destruction order is important -- though calling close()
115 /// should avoid any problems.
116 ///
117 /// The class should be used as follows for sequential samples: @code
118 ///
119 /// IMG_DeepPixelWriter pixel(dsm);
120 /// for (x, y) in raster {
121 /// if (pixel.open(x, y)) {
122 /// for (int i = 0; i < depth; i++)
123 /// data = pixel.writeOrdered(z, data, vsize);
124 /// pixel.close();
125 /// }
126 /// }
127 /// @endcode
128 ///
130 {
131 public:
134 
135  /// Ignore the desired sample compositing state in IMG_DeepShadow.
136  /// The default is to assume the incoming samples are pre-composited.
137  /// Writing raw samples will ignore compression levels, since the
138  /// compressors assume pre-composited samples.
139  void writeRawSamples(bool enable);
140 
141  /// Open a pixel for writing
142  bool open(int x, int y);
143 
144  /// Close the pixel. This is called automatically on destruction.
145  /// However, if an IMG_DeepPixelWriter and IMG_DeepShadow are created in
146  /// the same scope, the IMG_DeepPixelReader may hold onto references (and
147  /// cause crashing errors). Calling close() manually is a safe thing to
148  /// do.
149  bool close();
150 
151  /// Write data to the currently open pixel. This method inserts an
152  /// unordered data record with the given z-value and data into the
153  /// current pixel. vsize is the number of floats that are contained
154  /// in the data array.
155  ///
156  /// The first 3 floats of the data array must be the opacity (RGB). Any
157  /// extra channel data follows this according to the float_offset
158  /// associated with the channel. This data may be quantized to a single
159  /// float depending on the options.
160  ///
161  /// If @c vsize doesn't contain a full record, then this method will fail.
162  /// vsize must be greater or equal to 3 (depending on extra channels)
163  ///
164  /// Currently, mantra will always interpret the data as a rgb opacity
165  /// triple.
166  ///
167  /// The @c flags parameter is used to pass information to the
168  /// @c PXL_DeepSampleList interface. Possible values are:
169  /// - 0x00: No special meaning
170  /// - 0x01: Sample represents a volume
171  /// - 0x02: Sample is a matte surface
172  /// These values are found in the @c PXL_DeepSampleList::SampleFlag enum.
173  ///
174  /// The @c sampleid parameter specifies which pixel sample is associated
175  /// with these values (see @c sxres and @c syres on the create() method).
176  ///
177  /// The @c z value represents the "z-front" value for the depth sample.
178  /// For hard surfaces @c dz should be 0. For volumes @c dz should be set
179  /// to the extent of the volume sample so that the "z-back" data can be set
180  /// appropriately.
181  bool write(float z,
182  const float *chdata, int chsize,
183  int flags,
184  int sampleid,
185  float dz=0);
186 
187  /// Perform the same operation as write() except assume that data
188  /// is pre-sorted by increasing z-value. This method will perform
189  /// slightly better than write() as data does not need to be sorted.
190  bool writeOrdered(float z,
191  const float *chdata, int chsize,
192  int flags,
193  int sampleid,
194  float dz=0)
195  {
196  return write(z, chdata, chsize, flags, sampleid, dz);
197  }
198 
199  /// Alternatively, you can do something like: @code
200  /// PXL_DeepPixel pixel;
201  /// pixel.startPixel(x, y);
202  /// for (rec : records) pixel.store(rec);
203  /// write(pixel.closePixel(writer.compressor()));
204  /// @endcode
205  bool writePixel(int pixel_x, int pixel_y,
206  const PXL_DeepSampleListPtr &pixel);
207 
208  /// Access to the pixel compressor.
209  const PXL_DeepCompressorPtr &compressor() const { return myDeepCompressor; }
210 
211 private:
212  img_DeepShadow *myFile;
213  int myPixelX, myPixelY;
214  UT_UniquePtr<PXL_DeepPixel> myDeepPixel;
215  PXL_DeepCompressorPtr myDeepCompressor;
216  bool myWriteRaw;
217 };
218 
219 /// @brief Single channel of a Houdini DSM image
220 ///
221 /// A Houdini deep shadow/camera file can have any number of image channels
222 /// (planes). A DSM image contains a single channel for opacity. A deep
223 /// camera image has the opacity channel along with any number of extra image
224 /// channels.
226 {
227 public:
228  /// @param name The unique name of the DSM channel
229  /// @param float_offset
230  /// When data is read or written in deep shadow files, the pixel
231  /// data is interleaved. That is, the data for a single pixel can
232  /// be represented as an array of floats. Each channel has a
233  /// unique offset into the array. The user should @b not assume
234  /// that the offsets are contiguous. For example, the pixel data
235  /// might look like: @code
236  /// [ Of.r, // Opacity red
237  /// Of.g, // Opacity green
238  /// Of.b, // Opacity blue
239  /// Cf.r, // Color (red)
240  /// Cf.g, // Color (green)
241  /// Cf.b, // Color (blue)
242  /// s, // s coordinate
243  /// t, // t coordinate
244  /// N.x, // Normal x
245  /// N.y, // Normal y
246  /// N.z, // Normal z
247  /// ]
248  /// @endcode
249  /// Where the channels would be defined by: @code
250  /// IMG_DeepShadowChannel("Of", 0, 3);
251  /// IMG_DeepShadowChannel("Cf", 3, 3);
252  /// IMG_DeepShadowChannel("s", 6, 1);
253  /// IMG_DeepShadowChannel("t", 7, 1);
254  /// IMG_DeepShadowChannel("N", 8, 3);
255  /// @endcode
256  /// @param tuple_size Number of floats
257  /// @param storage
258  /// Storage type. This may be one of { "real16", "real32",
259  /// "real64" }. This value represents the storage of the channel
260  /// in the file.
261  /// @see IMG_DeepShadow::addExtraChannel()
262  IMG_DeepShadowChannel(const char *name,
263  int float_offset,
264  int tuple_size,
265  const char *storage="real32");
266 
267  bool operator==(const IMG_DeepShadowChannel &s) const;
268 
269  /// @{
270  /// Data acceess function
271  const char *getName() const { return myName.c_str(); }
272  const char *getStorage() const { return myStorage.c_str(); }
273  int getOffset() const { return myOffset; }
274  int getTupleSize() const { return myTupleSize; }
275  /// @}
276 
277 private:
278  UT_StringHolder myName;
279  UT_StringHolder myStorage;
280  int myOffset;
281  int myTupleSize;
282 };
283 
284 /// @brief Class to read or write deep shadow/camera images
285 ///
286 /// This class provides a creation interface for deep shadow maps.
287 /// The class can be used as follows: @code
288 /// setOption(...);
289 /// setOption(...);
290 /// ...
291 /// open(fname, xres, yres);
292 /// IMG_DeepPixelWriter writer;
293 /// foreach pixel loop
294 /// writer.open(pixel);
295 /// foreach record
296 /// writer.write(record);
297 /// end loop
298 /// writer.close();
299 /// end loop
300 /// close();
301 /// @endcode
302 ///
303 /// To read from an existing deep shadow map, the class can be used as
304 /// follows: @code
305 /// IMG_DeepShadow dsm;
306 /// IMG_DeepPixelReader pixel;
307 /// dsm.open(fname);
308 /// foreach (x,y) in raster:
309 /// pixel.open(x, y)
310 /// for (i = 0; i < pixel.getDepth(); i++)
311 /// pixel.getData(chp, i);
312 /// close();
313 /// @endcode
314 ///
315 /// @see
316 /// - TIL_TextureMap - for filtered evaluation of DSM/DCM's)
317 /// - IMG_DeepPixelReader - For thread-safe reading of DSM pixels
318 /// - IMG_DeepShadowChannel
320 {
321 public:
322  IMG_DeepShadow();
323  virtual ~IMG_DeepShadow();
324 
325  /// Certain channel names are reserved as "special" channels. These
326  /// channels have special interpretations for deep images (i.e. "Z",
327  /// "ZBack", etc.). Each format registers their special channel names
328  static void addSpecialChannel(const UT_StringHolder &channel_name,
330  static IMG_DeepPlaneMask isSpecialChannel(const char *name);
331 
332  /// Set a file creation option. Options must be set before the
333  /// file is opened with open() below.
334  ///
335  /// Currently (and this list may be out of date), the options are:
336  /// - "ofstorage" = one of { "int8", "int16", "int32", "int64",
337  /// "uint8", "uint16", "uint32", "uint64",
338  /// "real16", "real32", "real64" }
339  /// - "pzstorage" = one of { "int8" ... "real64" }
340  /// - "ofsize" = one of { "1", "3" }
341  /// - "compression = a value between "0" and "9" (lossyness)
342  /// - "zbias" = minimum delta between z-values (float value)
343  /// - "depth_mode" = one of { "nearest", "midpoint", "farthest" }
344  /// - "depth_interp" = one of { "discrete", "continuous" }
345  /// - "compositing" = "0" will turn off pre-compositing of the z-records
346  /// This is recommended when dealing with deep camera maps (i.e. if
347  /// there are extra channels)
348  void setOption(const char *option, const UT_StringHolder &value);
349  void setOption(const char *option, fpreal value);
350  void setOption(const char *option, int64 value);
351  void setOption(const char *option, int value)
352  { setOption(option, (int64)value); }
353 
354  /// Set options based on the "texture:*" options defined in the UT_Options.
355  /// The UT_Options will be checked for options:
356  /// - @c texture:ofstorage
357  /// - @c texture:pzstorage
358  /// - @c texture:ofsize
359  /// - @c etc.
360  void setOptions(const UT_Options &options);
361 
362  /// Print the current values of the file options into the work buffer
363  void printArgs(UT_WorkBuffer &wbuf, bool json);
364 
365  /// Get a description of the available options that can be provided in
366  /// setOption()
367  const char *getDescription();
368 
369  /// Add an extra channel to be stored along with Of and Pz. Any number of
370  /// channels may be added (though the file size will increase accordingly).
371  /// - The name must be unique among (and not Of or Pz)
372  /// - The float_offset is the offset into the "data" in the
373  /// IMG_DeepPixelWriter::write() method. Note that the opacity
374  /// must occupy the first 3
375  /// floats of the data array. So, the float_offset @b must be at least 3.
376  /// - The tuple_size is the number of elements in the channel
377  /// Currently, this must be 1, 3 or 4.
378  /// - The storage specifies the storage type (and uses the same
379  /// tokens as the "ofstorage" option (i.e. int8, int16, int32, int64,
380  /// uint8, uint16, uint32, uint64, real16, real32 or real64.
381  /// The extra channels must be added @b before open() is called.
382  bool addExtraChannel(const IMG_DeepShadowChannel &def,
383  const UT_Options *options=0);
384 
385  /// Open a deep shadow map for writing. This method will return false
386  /// if there were errors opening the texture.
387  /// The resolution of the image is specified by @c xres and @c yres, while
388  /// the @c sxres and @c syres parameters specify the samples per pixel
389  /// (i.e. 3x3 sampling). The pixel_aspect is typically 1.0, while the crop
390  /// can be a NULL ptr.
391  ///
392  /// If the sample resolution is unknown, you can set @c sxres and @c syres
393  /// to 1 (the @c sampleid should be set to 0).
394  /// @{
395  bool create(const char *name, int xres, int yres,
396  int sxres, int syres,
397  float pixel_aspect = 1.0,
398  const UT_DimRect *crop = NULL);
399  bool create(
400  const char *name,
401  const IMG_Stat &stat,
402  const IMG_FileParms *options = NULL,
403  const IMG_Format *fmt = NULL);
404  ///@}
405 
406  /// Open a deep shadow map for reading.
407  bool open(const char *name);
408 
409 
410  /// These methods are now deprecated in favor of the
411  /// IMG_DeepPixelWriter class, which allows thread-safe writes to
412  /// deep images.
413  /// {
414  SYS_DEPRECATED(13.0)
415  bool pixelStart(int x, int y);
416  SYS_DEPRECATED(13.0)
417  bool pixelWrite(float z, const float *data, int vsize);
418  SYS_DEPRECATED(13.0)
419  bool pixelWriteOrdered(float z, const float *data,
420  int vsize);
421  SYS_DEPRECATED(13.0)
422  bool pixelClose();
423  /// }
424 
425  /// Close the deep shadow map and write it to disk.
426  bool close();
427 
428 public:
429 
430  /// Get the resolution of the deep shadow map.
431  void resolution(int &xres, int &yres) const;
432 
433  /// Get the number of channels in the DSM
434  int getChannelCount() const;
435 
436  /// Get a channel definition
437  const IMG_DeepShadowChannel *getChannel(int i) const;
438 
439  /// Get UT_Option structure from the file. These options are stored with
440  /// the file and may be queried in VEX using teximport().
441  UT_SharedPtr<UT_Options> getTextureOptions() const;
442 
443  /// Store the UT_Options structure in the file. These options are stored with
444  /// the file and may be queried in VEX using teximport() on load.
445  bool setTextureOptions(const UT_Options &opts);
446 
447  /// @{
448  /// Extract the worldToCamera transform from a UT_Options. Returns false
449  /// if there was no matrix available.
450  ///
451  /// This extracts the "space:world" matrix from the UT_Options.
452  static bool getWorldToCamera(const UT_Options *options,
453  UT_Matrix4F &xform);
454  static bool getWorldToCamera(const UT_Options *options,
455  UT_Matrix4D &xform);
456  template <typename T>
457  bool getWorldToCamera(UT_Matrix4T<T> &xform) const
458  { return getWorldToCamera(getTextureOptions().get(),
459  xform); }
460  /// @}
461 
462  /// @{
463  /// Get the camera's projection transform from the file options. Returns
464  /// false if there was no matrix available.
465  /// If @c fit_z is true, the projection will attempt to fit the z
466  /// coordinates to the NDC near/far to the range (0,1). If the camera:clip
467  /// option is not saved, this will not be possible (z coordinates will
468  /// remain unchanged). The method will @b not fail if there is no
469  /// camera:clip saved, but the z coordinates will have unexpected values
470  ///
471  /// The method gets the values for the projection matrix from the following
472  /// options:
473  /// - float camera:zoom
474  /// - int camera:projection (optional, defaults to 0)
475  /// - float image:pixelaspect (optional, defaults to 1)
476  /// - vector4 image:window (optional, defaults to [0, 1, 0, 1])
477  /// - vector2 camera:clip (used iff @c fit_z is true, defaults to (0,1))
478  /// - float camera:orthowidth (required iff @c projection != 0)
479  static bool getCameraToNDC(const UT_Options *options,
480  UT_Matrix4F &xform,
481  int xres, int yres,
482  bool fit_z=true);
483  static bool getCameraToNDC(const UT_Options *options,
484  UT_Matrix4D &xform,
485  int xres, int yres,
486  bool fit_z=true);
487  template <typename T>
489  bool fit_z=true) const
490  {
491  int xres, yres;
492  resolution(xres, yres);
493  return getCameraToNDC(getTextureOptions().get(),
494  xform, xres, yres, fit_z);
495  }
496  /// @}
497 
498  /// @{
499  /// Get the world to camera NDC space transform using the file options.
500  /// Returns false if there is no matrix available.
501  /// If @c fit_z is true, the projection will attempt to fit the z
502  /// coordinates to the NDC near/far to the range (0,1). If the camera:clip
503  /// option is not saved, this will not be possible (z coordinates will
504  /// remain unchanged).
505  /// @note This simply returns getWorldToCamera()*getCameraToNDC()
506  static bool getWorldToNDC(const UT_Options *options,
507  UT_Matrix4F &xform,
508  int xres, int yres, bool fit_z);
509  static bool getWorldToNDC(const UT_Options *options,
510  UT_Matrix4D &xform,
511  int xres, int yres, bool fit_z);
512  template <typename T>
514  bool fit_z) const
515  {
516  int xres, yres;
517  resolution(xres, yres);
518  return getWorldToNDC(getTextureOptions().get(),
519  xform, xres, yres, fit_z);
520  }
521  /// @}
522 
523  /// Return deep stats
524  UT_SharedPtr<IMG_DeepStat> getDeepStat() const;
525 
526  float ofBias() const;
527  float zBias() const;
528 
529  /// Return the PXL_DeepChannelList being written to the DSM
530  const PXL_DeepChannelListPtr &deepChannels() const;
531 
532  /// Return the number of samples per pixel
533  int deepSampleListsPerPixel() const;
534 
535  /// Metadata to send to deep image file
536  void setWriteTag(
537  const char *tag,
538  int datasize,
539  const char *const *data);
540 
541  bool copyImageTextureOptions(const IMG_DeepShadow &src, bool clear_existing);
542 
543 protected:
544  /// Perform all computation for creating an image, but don't actually open
545  /// the IMG_File. This can be done when you want to make sure all the deep
546  /// information is set up properly, but don't actually want to create the
547  /// image. One example of this might be when doing distributed rendering.
548  ///
549  /// This takes the same arguments as @c create().
550  bool createStat(IMG_Stat &stat,
551  const char *name, int xres, int yres,
552  int sxres, int syres,
553  float pixel_aspect,
554  const UT_DimRect *crop);
555 
556 private:
557  friend class IMG_DeepPixelReader;
558  friend class IMG_DeepPixelWriter;
559 
560  bool openPixelRead(IMG_DeepPixelReader &h, int x, int y);
561  void closePixelRead(IMG_DeepPixelReader &h);
562 
563 private:
564  friend class img_DeepShadow;
565 
566 private:
568  img_DeepShadow *myFile;
569 };
570 
571 #endif
#define SYS_DEPRECATED(__V__)
Thread-safe convenience class to make reading DSM pixels easy.
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:847
Single channel of a Houdini DSM image.
const PXL_DeepCompressorPtr & compressor() const
Access to the pixel compressor.
Thread-safe convenience class to make writing DSM pixels easy.
GLbitfield flags
Definition: glcorearb.h:1595
GLint y
Definition: glcorearb.h:102
Class to read or write deep shadow/camera images.
png_uint_32 i
Definition: png.h:2877
void setOption(const char *option, int value)
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:137
long long int64
Definition: SYS_Types.h:107
#define IMG_API
Definition: IMG_API.h:10
const char * getName() const
bool getCameraToNDC(UT_Matrix4T< T > &xform, bool fit_z=true) const
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
Definition: UT_SharedPtr.h:28
int getTupleSize() const
IMG_DeepPlaneMask
Definition: IMG_DeepStat.h:35
GLboolean * data
Definition: glcorearb.h:130
GLuint const GLchar * name
Definition: glcorearb.h:785
virtual int open(float queuesize)
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2001
GLsizei const GLfloat * value
Definition: glcorearb.h:823
double fpreal
Definition: SYS_Types.h:270
A map of string to various well defined value types.
Definition: UT_Options.h:42
virtual void close()
bool getWorldToNDC(UT_Matrix4T< T > &xform, bool fit_z) const
File options for manipulating image data on load or save. This class allows you to modify the incomin...
Definition: IMG_FileParms.h:34
GLint GLenum GLint x
Definition: glcorearb.h:408
Contains the details of a specific image file, used by IMG_File. This class contains all the high-lev...
Definition: IMG_Stat.h:40
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:107
getOption("OpenEXR.storage") storage
Definition: HDK_Image.dox:276
UT_SharedPtr< PXL_DeepCompressor > PXL_DeepCompressorPtr
Definition: PXL_Forward.h:26
#define const
Definition: zconf.h:214
const char * getStorage() const
void write(T &out, bool v)
Definition: ImfXdr.h:332
bool writeOrdered(float z, const float *chdata, int chsize, int flags, int sampleid, float dz=0)
GLenum src
Definition: glcorearb.h:1792