RixBxdfLobe.h Source File

RixBxdfLobe.h
1 #ifndef RixBxdfLobe_h
2 #define RixBxdfLobe_h
3 /* $Revision: #5 $ $Date: 2015/07/29 $
4 # ------------------------------------------------------------------------------
5 #
6 # Copyright (c) 2014 Pixar Animation Studios. All rights reserved.
7 #
8 # The information in this file (the "Software") is provided for the
9 # exclusive use of the software licensees of Pixar. Licensees have
10 # the right to incorporate the Software into other products for use
11 # by other authorized software licensees of Pixar, without fee.
12 # Except as expressly permitted herein, the Software may not be
13 # disclosed to third parties, copied or duplicated in any form, in
14 # whole or in part, without the prior written permission of
15 # Pixar Animation Studios.
16 #
17 # The copyright notices in the Software and this entire statement,
18 # including the above license grant, this restriction and the
19 # following disclaimer, must be included in all copies of the
20 # Software, in whole or in part, and all permitted derivative works of
21 # the Software, unless such copies or derivative works are solely
22 # in the form of machine-executable object code generated by a
23 # source language processor.
24 #
25 # PIXAR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
26 # ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
27 # SHALL PIXAR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
28 # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
29 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
30 # ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
31 # SOFTWARE.
32 #
33 # Pixar
34 # 1200 Park Ave
35 # Emeryville CA 94608
36 #
37 # ------------------------------------------------------------------------------
38 */
39 
40 #include "RixInterfaces.h"
41 
42 #include <cstring>
43 #include <cassert>
44 
46 static const int k_RixBXMaxNumDiffuseLobes = 4;
47 
49 static const int k_RixBXMaxNumSpecularLobes = 8;
50 
52 static const int k_RixBXMaxNumUserLobes = 8;
53 
56 {
58  PRMAN_INLINE RixBXLobeSampled();
59 
61  PRMAN_INLINE RixBXLobeSampled(unsigned short serialized);
62 
64  PRMAN_INLINE RixBXLobeSampled(bool discrete, bool specular,
65  bool reflect, bool user,
66  unsigned char lpeId, unsigned char lobeId);
67 
68 
69  // CompareLobeID: returns true if rhs is the same as this lobeid.
70  PRMAN_INLINE bool CompareLobeID(RixBXLobeSampled const &rhs)
71  {
72  return (fields.bits.valid && rhs.fields.bits.valid &&
73  fields.bits.specular == rhs.fields.bits.specular &&
74  fields.bits.user == rhs.fields.bits.user &&
75  fields.bits.lobeId == rhs.fields.bits.lobeId);
76  }
77 
78  // Read-only accessors; these all verify that the valid bit is set before
79  // returning true.
80  PRMAN_INLINE bool GetValid() const;
81  PRMAN_INLINE bool GetDiscrete() const;
82  PRMAN_INLINE bool GetSolidAngle() const;
83  PRMAN_INLINE bool GetDiffuse() const;
84  PRMAN_INLINE bool GetSpecular() const;
85  PRMAN_INLINE bool GetReflect() const;
86  PRMAN_INLINE bool GetTransmit(bool *entering=NULL) const;
87  PRMAN_INLINE bool GetEntering() const; // only valid for Transmit
88  PRMAN_INLINE bool GetContinuation() const;
89  PRMAN_INLINE bool GetScattering() const;
90  PRMAN_INLINE bool GetUser() const;
91  PRMAN_INLINE unsigned char GetLpeId() const;
92  PRMAN_INLINE unsigned char GetLobeId() const;
93 
94  // Set individual fields (only SetValid() changes the valid bit).
95  PRMAN_INLINE void SetValid(bool val);
96  PRMAN_INLINE void SetDiscrete(bool val);
97  PRMAN_INLINE void SetSpecular(bool val);
98  PRMAN_INLINE void SetReflect();
99  PRMAN_INLINE void SetTransmit(bool entering);
100  PRMAN_INLINE void SetEntering(bool entering); // valid only for Transmit
101  PRMAN_INLINE void SetContinuation(bool val);
102  PRMAN_INLINE void SetUser(bool val);
103  PRMAN_INLINE void SetLpeId(unsigned char val);
104  PRMAN_INLINE void SetLobeId(unsigned char val);
105 
107  PRMAN_INLINE void Set(bool vDiscrete, bool vSpecular, bool vReflect,
108  bool vContinuation, bool vUser,
109  unsigned char vLpeId, unsigned char vLobeid);
110 
111  // Convert to a serialized integral representation.
112  PRMAN_INLINE unsigned short Serialize() const;
113 
114  struct Bitfield
115  {
116  unsigned short valid : 1;
117  unsigned short discrete : 1;
118  unsigned short specular : 1;
120  unsigned short reflect : 1;
121  unsigned short entering : 1;
122  unsigned short continuation : 1;
124  unsigned short user : 1;
125  unsigned short lpeId : 3;
126  unsigned short lobeId : 3;
127  unsigned short unused : 3;
128  };
129 
130  union Converter
131  {
132  Bitfield bits;
133  unsigned short us;
134  };
135 
136  private:
137  Converter fields;
138 };
139 
142 PRMAN_INLINE
143 RixBXLobeSampled RixBXLookupLobeByName(RixContext &ctx,
144  bool discrete, bool specular,
145  bool reflect, bool user,
146  unsigned char lobeId, char const *name);
147 
151 {
153  PRMAN_INLINE RixBXLobeTraits();
154 
156  PRMAN_INLINE RixBXLobeTraits(unsigned serialized);
157 
159  PRMAN_INLINE RixBXLobeTraits(bool discrete, bool reflect, bool transmit,
160  unsigned short D, unsigned short S, unsigned short U);
161 
163  PRMAN_INLINE explicit RixBXLobeTraits(RixBXLobeSampled lobe);
164 
165  // Read-only accessors; return individual fields.
166  PRMAN_INLINE bool GetDiscrete() const;
167  PRMAN_INLINE bool GetReflect() const;
168  PRMAN_INLINE bool GetTransmit() const;
169  PRMAN_INLINE bool GetContinuation() const;
170  PRMAN_INLINE unsigned short GetDiffuse() const;
171  PRMAN_INLINE unsigned short GetSpecular() const;
172  PRMAN_INLINE unsigned short GetUser() const;
173 
174  PRMAN_INLINE bool GetMaxSpecularDepth() const;
175  PRMAN_INLINE bool GetMaxDiffuseDepth() const;
176 
177  // Set individual fields.
178  PRMAN_INLINE void SetDiscrete(bool val);
179  PRMAN_INLINE void SetReflect(bool val);
180  PRMAN_INLINE void SetTransmit(bool val);
181  PRMAN_INLINE void SetContinuation(bool val);
182  PRMAN_INLINE void SetMaxSpecularDepth(bool val);
183  PRMAN_INLINE void SetMaxDiffuseDepth(bool val);
184  PRMAN_INLINE void SetDiffuse(unsigned short bits);
185  PRMAN_INLINE void SetSpecular(unsigned short bits);
186  PRMAN_INLINE void SetUser(unsigned short bits);
187 
189  PRMAN_INLINE void SetNone();
190 
195  PRMAN_INLINE void SetAll();
196 
199  PRMAN_INLINE bool HasAny() const;
200 
203  PRMAN_INLINE bool HasAnyDiffSpec() const;
204 
207  PRMAN_INLINE bool HasAnyDiffuse() const;
208 
211  PRMAN_INLINE bool HasAnySpecular() const;
212 
214  PRMAN_INLINE bool HasAnyUser() const;
215 
216  // Convert to a serialized integral representation.
217  PRMAN_INLINE unsigned Serialize() const;
218 
220  PRMAN_INLINE RixBXLobeTraits const &operator &=(RixBXLobeTraits const &rhs);
221 
223  PRMAN_INLINE RixBXLobeTraits const &operator |=(RixBXLobeTraits const &rhs);
224 
225  struct Bitfield
226  {
227  unsigned discreteSubset : 1;
228  unsigned reflectSubset : 1;
230  unsigned transmitSubset : 1;
231  unsigned continuationSubset : 1;
232  unsigned D : k_RixBXMaxNumDiffuseLobes;
233  unsigned S : k_RixBXMaxNumSpecularLobes;
234  unsigned U : k_RixBXMaxNumUserLobes;
235 
236  unsigned maxspeculardepth : 1;
237  unsigned maxdiffusedepth : 1;
238  unsigned unused : 6;
239  };
240 
241  union Converter
242  {
243  Bitfield bits;
244  unsigned us;
245  };
246 
247  private:
248  Converter fields;
249 };
250 
252 PRMAN_INLINE RixBXLobeTraits operator & (RixBXLobeTraits const &lhs,
253  RixBXLobeTraits const &rhs);
254 
256 PRMAN_INLINE RixBXLobeTraits operator | (RixBXLobeTraits const &lhs,
257  RixBXLobeTraits const &rhs);
258 
260 static const RixBXLobeTraits k_RixBXTraitsNullLobe
261  (false, false, false, 0x0, 0x0, 0x0);
262 static const RixBXLobeTraits k_RixBXTraitsReflectDiffuse
263  (false, true, false, 0xF, 0x0, 0x0);
264 static const RixBXLobeTraits k_RixBXTraitsReflectSpecular
265  (false, true, false, 0x0, 0xFF, 0x0);
266 static const RixBXLobeTraits k_RixBXTraitsTransmitDiffuse
267  (false, false, true, 0xF, 0x0, 0x0);
268 static const RixBXLobeTraits k_RixBXTraitsTransmitSpecular
269  (false, false, true, 0x0, 0xFF, 0x0);
270 static const RixBXLobeTraits k_RixBXTraitsAllDiffuse
271  (false, true, true, 0xF, 0x0, 0x0);
272 static const RixBXLobeTraits k_RixBXTraitsAllSpecular
273  (false, true, true, 0x0, 0xFF, 0x0);
274 static const RixBXLobeTraits k_RixBXTraitsAllUser
275  (false, false, false, 0x0, 0x0, 0xFF);
276 static const RixBXLobeTraits k_RixBXTraitsAllReflect
277  (false, true, false, 0x0F, 0xFF, 0x0);
278 static const RixBXLobeTraits k_RixBXTraitsAllTransmit
279  (false, false, true, 0x0F, 0xFF, 0x0);
280 static const RixBXLobeTraits k_RixBXTraitsAllLobe
281  (false, true, true, 0x0F, 0xFF, 0xFF);
282 
283 
285 {
287  PRMAN_INLINE RixBXActiveLobeWeights();
288 
290  PRMAN_INLINE RixBXActiveLobeWeights(RixBXLobeTraits lobeTraits,
291  int numDiffuseLobes,
292  int numSpecularLobes,
293  int numUserLobes,
294  RtColorRGB *diffuseLobes[],
295  RtColorRGB *specularLobes[],
296  RtColorRGB *userLobes[],
297  unsigned char diffuseLpeIds[],
298  unsigned char specularLpeIds[],
299  unsigned char userLpeIds[],
300  int offset = 0);
301 
303  PRMAN_INLINE RixBXActiveLobeWeights(RixBXActiveLobeWeights const &that);
304 
306  PRMAN_INLINE RixBXActiveLobeWeights &operator=
307  (RixBXActiveLobeWeights const &that);
308 
309  // Get the pointer to the array of weights for a diffuse or specular lobe.
310  PRMAN_INLINE RtColorRGB const *GetDiffuseLobe(int i) const;
311  PRMAN_INLINE RtColorRGB const *GetSpecularLobe(int i) const;
312  PRMAN_INLINE RtColorRGB const *GetUserLobe(int i) const;
313  PRMAN_INLINE RtColorRGB *GetDiffuseLobe(int i);
314  PRMAN_INLINE RtColorRGB *GetSpecularLobe(int i);
315  PRMAN_INLINE RtColorRGB *GetUserLobe(int i);
316 
317  // Clears all diffuse or specular lobes from active lobes list
318  PRMAN_INLINE void ClearAllDiffuseLobes();
319  PRMAN_INLINE void ClearAllSpecularLobes();
320  PRMAN_INLINE void ClearAllUserLobes();
321 
322  // Get or set the current offset into array of weights.
323  PRMAN_INLINE int GetOffset() const;
324  PRMAN_INLINE void SetOffset(int offset);
325 
326  // Get or set the lobe traits.
327  PRMAN_INLINE RixBXLobeTraits GetLobeTraits() const;
328  PRMAN_INLINE void SetLobeTraits(RixBXLobeTraits lobes);
329 
330  // Get the number of diffuse or specular lobes.
331  PRMAN_INLINE unsigned char GetNumDiffuseLobes() const;
332  PRMAN_INLINE unsigned char GetNumSpecularLobes() const;
333  PRMAN_INLINE unsigned char GetNumUserLobes() const;
334 
335  // Get the original LPE id of a diffuse or specular lobe.
336  PRMAN_INLINE unsigned char GetDiffuseLpeId(int i) const;
337  PRMAN_INLINE unsigned char GetSpecularLpeId(int i) const;
338  PRMAN_INLINE unsigned char GetUserLpeId(int i) const;
339 
340  // Return the sum at a particular index in the array of lobe weights.
341  PRMAN_INLINE RtColorRGB SumAtIndex(int index,
342  bool includeUserLobes = false) const;
343 
344  // Multiply by a value at a particular index in the array of lobe weights.
345  PRMAN_INLINE void MultiplyByWeightAtIndex(int index, float wgt,
346  bool includeUserLobes = false);
347  PRMAN_INLINE void MultiplyByWeightAtIndex(int index, RtColorRGB const &wgt,
348  bool includeUserLobes = false);
349 
350  private:
351  friend class RixBXLobeWeights;
352 
353  // Ptrs to diffuse and specular weights
354  RtColorRGB *m_diffuseLobes[k_RixBXMaxNumDiffuseLobes];
355  RtColorRGB *m_specularLobes[k_RixBXMaxNumSpecularLobes];
356  RtColorRGB *m_userLobes[k_RixBXMaxNumUserLobes];
357 
358  int m_offset; // Offset into arrays
359  RixBXLobeTraits m_lobeTraits; // Active lobe traits
360  unsigned char m_numDiffuseLobes; // Diff lobe count
361  unsigned char m_numSpecularLobes; // Spec lobe count
362  unsigned char m_numUserLobes; // User lobe count
363 
364  // Diffuse and specular LPE ids.
365  unsigned char m_diffuseLpeIds[k_RixBXMaxNumDiffuseLobes];
366  unsigned char m_specularLpeIds[k_RixBXMaxNumSpecularLobes];
367  unsigned char m_userLpeIds[k_RixBXMaxNumUserLobes];
368 };
369 
370 // RixBXLobeWeights distributes weights into qualitative properties.
372 {
375  PRMAN_INLINE RixBXLobeWeights();
376 
378  PRMAN_INLINE RixBXLobeWeights(int numPoints,
379  int numDiffuseLobes,
380  int numSpecularLobes,
381  int numUserLobes,
382  RtColorRGB *diffuseLobes[],
383  RtColorRGB *specularLobes[],
384  RtColorRGB *userLobes[],
385  int offset = 0);
386 
388  PRMAN_INLINE RixBXLobeWeights(RixBXLobeWeights const &that);
389 
391  PRMAN_INLINE RixBXLobeWeights &operator= (RixBXLobeWeights const &that);
392 
393  // Get the pointer to the array of weights for a diffuse or specular lobe.
394  PRMAN_INLINE RtColorRGB const *GetDiffuseLobe(int i) const;
395  PRMAN_INLINE RtColorRGB const *GetSpecularLobe(int i) const;
396  PRMAN_INLINE RtColorRGB const *GetUserLobe(int i) const;
397  PRMAN_INLINE RtColorRGB *GetDiffuseLobe(int i);
398  PRMAN_INLINE RtColorRGB *GetSpecularLobe(int i);
399  PRMAN_INLINE RtColorRGB *GetUserLobe(int i);
400 
401  // Get or set the current number of points in the arrays of weights.
402  PRMAN_INLINE int GetNumPoints() const;
403  PRMAN_INLINE void SetNumPoints(int numPoints);
404 
405  // Get or set the current offset into array of weights.
406  PRMAN_INLINE int GetOffset() const;
407  PRMAN_INLINE void SetOffset(int offset);
408 
409  // Get, set or add to the active lobe traits.
410  PRMAN_INLINE RixBXLobeTraits GetActiveLobeTraits() const;
411  PRMAN_INLINE void SetActiveLobeTraits(RixBXLobeTraits lobes);
412  PRMAN_INLINE void AddActiveLobeTraits(RixBXLobeTraits lobes);
413 
414  // Get the number of diffuse or specular lobes.
415  PRMAN_INLINE int GetNumDiffuseLobes() const;
416  PRMAN_INLINE int GetNumSpecularLobes() const;
417  PRMAN_INLINE int GetNumUserLobes() const;
418 
421  PRMAN_INLINE RtColorRGB *AddActiveLobe(RixBXLobeSampled lobe,
422  bool doInitializeWeights = true);
423 
425  PRMAN_INLINE void GetActiveLobes(RixBXActiveLobeWeights &r);
426 
429  PRMAN_INLINE void GetActiveLobesIntersection
430  (RixBXLobeWeights &rhs,
431  RixBXActiveLobeWeights &activeLhs,
432  RixBXActiveLobeWeights &activeRhs);
433 
434  // Copy over just the active lobe weights in 'src' at the given index into
435  // the lobe weights. Any lobes that are not present in 'src' will not be
436  // updated in this instance.
437  PRMAN_INLINE void CopyWeightAtIndex(int index,
438  RixBXActiveLobeWeights const &src,
439  bool includeUserLobes = false);
440 
441  // Add in just the active lobe weights in 'src' at the given index into
442  // the lobe weights. Any lobes that are not present in 'src' will not be
443  // updated in this instance.
444  PRMAN_INLINE void AddWeightAtIndex(int index,
445  RixBXActiveLobeWeights const &src,
446  bool includeUserLobes = false);
447 
448  private:
449  // Ptrs to diffuse and specular weights
450  RtColorRGB *m_diffuseLobes[k_RixBXMaxNumDiffuseLobes];
451  RtColorRGB *m_specularLobes[k_RixBXMaxNumSpecularLobes];
452  RtColorRGB *m_userLobes[k_RixBXMaxNumUserLobes];
453 
454  int m_numPoints; // Size of each array
455  int m_offset; // Offset into arrays
456  RixBXLobeTraits m_activeLobeTraits; // Active lobe traits
457  unsigned char m_numDiffuseLobes; // Diff lobe count
458  unsigned char m_numSpecularLobes; // Spec lobe count
459  unsigned char m_numUserLobes; // User lobe count
460 };
461 
462 //
463 // --- inline implementations of classes above ---
464 //
465 
466 //
467 // class RixBXLobeSampled inline implementation
468 //
469 
470 PRMAN_INLINE
472 {
473  /* Init all fields to zero. We write one instruction that has the
474  * same effect as performing the following assignments:
475 
476  fields.bits.valid = 0;
477  fields.bits.discrete = 0;
478  fields.bits.specular = 0;
479  fields.bits.reflect = 0;
480  fields.bits.entering = 0;
481  fields.bits.continuation = 0;
482  fields.bits.user = 0;
483  fields.bits.lpeId = 0;
484  fields.bits.lobeId = 0;
485  fields.bits.unused = 0;
486  */
487 
488  fields.us = 0;
489 }
490 
491 PRMAN_INLINE
492 RixBXLobeSampled::RixBXLobeSampled(unsigned short serialized)
493 {
494  fields.us = serialized;
495 }
496 
497 PRMAN_INLINE
498 RixBXLobeSampled::RixBXLobeSampled(bool discreteV, bool specularV,
499  bool reflectV, bool userV,
500  unsigned char lpeIdV, unsigned char lobeIdV)
501 {
502  fields.bits.valid = 1;
503  fields.bits.discrete = discreteV;
504  fields.bits.specular = specularV;
505  fields.bits.reflect = reflectV;
506  fields.bits.entering = 0;
507  fields.bits.continuation = 0;
508  fields.bits.user = userV;
509  fields.bits.lpeId = lpeIdV & 0x7;
510  fields.bits.lobeId = lobeIdV & 0x7;
511  fields.bits.unused = 0;
512 }
513 
514 PRMAN_INLINE
515 bool RixBXLobeSampled::GetValid() const
516 {
517  return fields.bits.valid;
518 }
519 
520 PRMAN_INLINE
521 bool RixBXLobeSampled::GetDiscrete() const
522 {
523  return fields.bits.valid && fields.bits.discrete;
524 }
525 
526 PRMAN_INLINE
527 bool RixBXLobeSampled::GetSolidAngle() const
528 {
529  return fields.bits.valid && !fields.bits.discrete;
530 }
531 
532 PRMAN_INLINE
533 bool RixBXLobeSampled::GetDiffuse() const
534 {
535  return fields.bits.valid && !fields.bits.specular;
536 }
537 
538 PRMAN_INLINE
539 bool RixBXLobeSampled::GetSpecular() const
540 {
541  return fields.bits.valid && fields.bits.specular;
542 }
543 
544 PRMAN_INLINE
545 bool RixBXLobeSampled::GetReflect() const
546 {
547  return fields.bits.valid && fields.bits.reflect;
548 }
549 
550 PRMAN_INLINE
551 bool RixBXLobeSampled::GetTransmit(bool *enteringV) const
552 {
553  bool transmit = fields.bits.valid && !fields.bits.reflect;
554  if(enteringV)
555  *enteringV = fields.bits.entering && transmit;
556  return transmit;
557 }
558 
559 PRMAN_INLINE
560 bool RixBXLobeSampled::GetEntering() const
561 {
562  return fields.bits.valid && !fields.bits.reflect && fields.bits.entering;
563 }
564 
565 PRMAN_INLINE
566 bool RixBXLobeSampled::GetContinuation() const
567 {
568  return fields.bits.valid && fields.bits.continuation;
569 }
570 
571 PRMAN_INLINE
572 bool RixBXLobeSampled::GetScattering() const
573 {
574  return fields.bits.valid && !fields.bits.continuation;
575 }
576 
577 PRMAN_INLINE
578 bool RixBXLobeSampled::GetUser() const
579 {
580  return fields.bits.valid && fields.bits.user;
581 }
582 
583 PRMAN_INLINE
584 unsigned char RixBXLobeSampled::GetLpeId() const
585 {
586  return (unsigned char) (fields.bits.valid ? fields.bits.lpeId : 0);
587 }
588 
589 PRMAN_INLINE
590 unsigned char RixBXLobeSampled::GetLobeId() const
591 {
592  return (unsigned char) (fields.bits.valid ? fields.bits.lobeId : 0);
593 }
594 
595 PRMAN_INLINE
596 void RixBXLobeSampled::SetValid(bool val)
597 {
598  fields.bits.valid = val;
599 }
600 
601 PRMAN_INLINE
602 void RixBXLobeSampled::SetDiscrete(bool val)
603 {
604  fields.bits.discrete = val;
605 }
606 
607 PRMAN_INLINE
608 void RixBXLobeSampled::SetSpecular(bool val)
609 {
610  fields.bits.specular = val;
611 }
612 
613 PRMAN_INLINE
614 void RixBXLobeSampled::SetReflect()
615 {
616  fields.bits.reflect = 1;
617 }
618 
619 PRMAN_INLINE
620 void RixBXLobeSampled::SetTransmit(bool enterval)
621 {
622  fields.bits.reflect = 0;
623  fields.bits.entering = enterval;
624 }
625 
626 PRMAN_INLINE
627 void RixBXLobeSampled::SetEntering(bool enterval)
628 {
629  // valid only for Transmit
630  assert(fields.bits.reflect == 0);
631  fields.bits.entering = enterval;
632 }
633 
634 PRMAN_INLINE
635 void RixBXLobeSampled::SetContinuation(bool val)
636 {
637  fields.bits.continuation = val;
638 }
639 
640 PRMAN_INLINE
641 void RixBXLobeSampled::SetUser(bool val)
642 {
643  fields.bits.user = val;
644 }
645 
646 PRMAN_INLINE
647 void RixBXLobeSampled::SetLpeId(unsigned char val)
648 {
649  fields.bits.lpeId = val & 0x7;
650 }
651 
652 PRMAN_INLINE
653 void RixBXLobeSampled::SetLobeId(unsigned char val)
654 {
655  fields.bits.lobeId = val & 0x7;
656 }
657 
658 PRMAN_INLINE
659 void RixBXLobeSampled::Set(bool vDiscrete, bool vSpecular, bool vReflect,
660  bool vContinuation, bool vUser,
661  unsigned char vLpeId, unsigned char vLobeId)
662 {
663  fields.bits.valid = 1;
664  fields.bits.discrete = vDiscrete;
665  fields.bits.specular = vSpecular;
666  fields.bits.reflect = vReflect;
667  fields.bits.continuation = vContinuation;
668  fields.bits.entering = 0;
669  fields.bits.user = vUser;
670  fields.bits.lpeId = vLpeId & 0x7;
671  fields.bits.lobeId = vLobeId & 0x7;
672  fields.bits.unused = 0;
673 }
674 
675 PRMAN_INLINE
676 unsigned short RixBXLobeSampled::Serialize() const
677 {
678  return fields.us;
679 }
680 
681 //
682 // RixBXLookupLobeByName() inline implementation
683 //
684 
685 PRMAN_INLINE
686 RixBXLobeSampled RixBXLookupLobeByName(RixContext &ctx,
687  bool discrete, bool specular,
688  bool reflect, bool user,
689  unsigned char lobeId, char const *name)
690 {
691  unsigned char lpeId = 0;
692  int numPotentialLobes = 0;
693 
694  if (RixLPEInfo *lpeInfo = (RixLPEInfo *) ctx.GetRixInterface(k_RixLPEInfo))
695  {
696  lpeId = (unsigned char)lpeInfo->GetLpeIdByName(
697  discrete, specular, reflect, user, lobeId, name);
698 
699  if (user)
700  numPotentialLobes = lpeInfo->GetNumPotentialUserLobes();
701  else if (!specular)
702  numPotentialLobes = lpeInfo->GetNumPotentialDiffuseLobes();
703  else
704  numPotentialLobes = lpeInfo->GetNumPotentialSpecularLobes();
705  }
706 
707  // If the returned lpeId is greater than the number of
708  // potential lobes, then just be safe and return an invalid
709  // RixBXLobeSampled() struct.
710  if (lpeId >= numPotentialLobes)
711  {
712  return RixBXLobeSampled();
713  }
714  else
715  {
716  return RixBXLobeSampled(discrete, specular, reflect, user,
717  lpeId, lobeId);
718  }
719 }
720 
721 //
722 // class RixBXLobeTraits inline implementation.
723 //
724 
725 PRMAN_INLINE
727 {
728  SetNone();
729 }
730 
731 PRMAN_INLINE
733 {
734  fields.us = serialized;
735 }
736 
737 PRMAN_INLINE
738 RixBXLobeTraits::RixBXLobeTraits(bool discrete, bool reflect, bool transmit,
739  unsigned short D, unsigned short S, unsigned short U)
740 {
741  assert(sizeof(fields.bits) == sizeof(unsigned));
742  fields.bits.discreteSubset = discrete;
743  fields.bits.reflectSubset = reflect;
744  fields.bits.transmitSubset = transmit;
745  fields.bits.continuationSubset = 0;
746  fields.bits.D = D & 0x0F;
747  fields.bits.S = S & 0xFF;
748  fields.bits.U = U & 0xFF;
749  fields.bits.maxspeculardepth = 0;
750  fields.bits.maxdiffusedepth = 0;
751  fields.bits.unused = 0;
752 }
753 
754 PRMAN_INLINE
756 {
757  if (lobe.GetValid())
758  {
759  if (lobe.GetUser())
760  {
761  fields.bits.discreteSubset = 0;
762  fields.bits.reflectSubset = 0;
763  fields.bits.transmitSubset = 0;
764  fields.bits.continuationSubset = 0;
765 
766  fields.bits.D = 0;
767  fields.bits.S = 0;
768  if (lobe.GetLpeId() < k_RixBXMaxNumUserLobes)
769  fields.bits.U = (1 << lobe.GetLpeId()) & 0xFF;
770  else
771  fields.bits.U = 0;
772  }
773  else
774  {
775  fields.bits.discreteSubset = lobe.GetDiscrete();
776  fields.bits.reflectSubset = lobe.GetReflect();
777  fields.bits.transmitSubset = lobe.GetTransmit();
778  fields.bits.continuationSubset = lobe.GetContinuation();
779 
780  if (lobe.GetDiffuse() && lobe.GetLpeId() < k_RixBXMaxNumDiffuseLobes)
781  fields.bits.D = (1 << lobe.GetLpeId()) & 0x0F;
782  else
783  fields.bits.D = 0;
784  if (lobe.GetSpecular() && lobe.GetLpeId() < k_RixBXMaxNumSpecularLobes)
785  fields.bits.S = (1 << lobe.GetLpeId()) & 0xFF;
786  else
787  fields.bits.S = 0;
788  fields.bits.U = 0;
789  }
790  }
791  else
792  {
793  SetNone();
794  }
795  fields.bits.maxspeculardepth = 0;
796  fields.bits.maxdiffusedepth = 0;
797 }
798 
799 PRMAN_INLINE
800 bool RixBXLobeTraits::GetDiscrete() const
801 {
802  return fields.bits.discreteSubset;
803 }
804 
805 PRMAN_INLINE
806 bool RixBXLobeTraits::GetReflect() const
807 {
808  return fields.bits.reflectSubset;
809 }
810 
811 PRMAN_INLINE
812 bool RixBXLobeTraits::GetTransmit() const
813 {
814  return fields.bits.transmitSubset;
815 }
816 
817 PRMAN_INLINE
818 bool RixBXLobeTraits::GetContinuation() const
819 {
820  return fields.bits.continuationSubset;
821 }
822 
823 PRMAN_INLINE
824 unsigned short RixBXLobeTraits::GetDiffuse() const
825 {
826  return static_cast<unsigned short>(fields.bits.D);
827 }
828 
829 PRMAN_INLINE
830 unsigned short RixBXLobeTraits::GetSpecular() const
831 {
832  return static_cast<unsigned short>(fields.bits.S);
833 }
834 
835 PRMAN_INLINE
836 unsigned short RixBXLobeTraits::GetUser() const
837 {
838  return static_cast<unsigned short>(fields.bits.U);
839 }
840 
841 PRMAN_INLINE
842 bool RixBXLobeTraits::GetMaxSpecularDepth() const
843 {
844  return fields.bits.maxspeculardepth;
845 }
846 
847 PRMAN_INLINE
848 bool RixBXLobeTraits::GetMaxDiffuseDepth() const
849 {
850  return fields.bits.maxdiffusedepth;
851 }
852 
853 PRMAN_INLINE
854 void RixBXLobeTraits::SetDiscrete(bool val)
855 {
856  fields.bits.discreteSubset = val;
857 }
858 
859 PRMAN_INLINE
860 void RixBXLobeTraits::SetReflect(bool val)
861 {
862  fields.bits.reflectSubset = val;
863 }
864 
865 PRMAN_INLINE
866 void RixBXLobeTraits::SetTransmit(bool val)
867 {
868  fields.bits.transmitSubset = val;
869 }
870 
871 PRMAN_INLINE
872 void RixBXLobeTraits::SetContinuation(bool val)
873 {
874  fields.bits.continuationSubset = val;
875 }
876 
877 PRMAN_INLINE
878 void RixBXLobeTraits::SetDiffuse(unsigned short val)
879 {
880  fields.bits.D = static_cast<unsigned>(val & 0x0F);
881 }
882 
883 PRMAN_INLINE
884 void RixBXLobeTraits::SetSpecular(unsigned short val)
885 {
886  fields.bits.S = static_cast<unsigned>(val & 0xFF);
887 }
888 
889 PRMAN_INLINE
890 void RixBXLobeTraits::SetUser(unsigned short val)
891 {
892  fields.bits.U = static_cast<unsigned>(val & 0xFF);
893 }
894 
895 PRMAN_INLINE
896 void RixBXLobeTraits::SetMaxSpecularDepth(bool val)
897 {
898  fields.bits.maxspeculardepth = val;
899 }
900 
901 PRMAN_INLINE
902 void RixBXLobeTraits::SetMaxDiffuseDepth(bool val)
903 {
904  fields.bits.maxdiffusedepth = val;
905 }
906 
907 PRMAN_INLINE
909 {
910  /* Init all fields to zero. We write one instruction that has the
911  * same effect as performing the following assignments:
912 
913  fields.bits.discreteSubset = 0;
914  fields.bits.reflectSubset = 0;
915  fields.bits.transmitSubset = 0;
916  fields.bits.continuationSubset = 0;
917  fields.bits.D = 0;
918  fields.bits.S = 0;
919  fields.bits.U = 0;
920  fields.bits.maxspeculardepth = 0;
921  fields.bits.maxdiffusedepth = 0;
922  */
923 
924  fields.us = 0;
925 }
926 
927 PRMAN_INLINE
929 {
930  fields.bits.discreteSubset = 0;
931  fields.bits.reflectSubset = 1;
932  fields.bits.transmitSubset = 1;
933  fields.bits.continuationSubset = 0;
934  fields.bits.maxspeculardepth = 0;
935  fields.bits.maxdiffusedepth = 0;
936  fields.bits.D = 0x0F;
937  fields.bits.S = 0xFF;
938  fields.bits.U = 0xFF;
939 }
940 
941 PRMAN_INLINE
943 {
944  return HasAnyDiffSpec() || HasAnyUser();
945 }
946 
947 PRMAN_INLINE
949 {
950  return (fields.bits.D | fields.bits.S) &&
951  (fields.bits.reflectSubset |
952  fields.bits.transmitSubset |
953  fields.bits.continuationSubset);
954 }
955 
956 PRMAN_INLINE
958 {
959  return (fields.bits.D != 0) && (fields.bits.reflectSubset ||
960  fields.bits.transmitSubset);
961 }
962 
963 PRMAN_INLINE
965 {
966  return (fields.bits.S != 0) && (fields.bits.reflectSubset ||
967  fields.bits.transmitSubset);
968 }
969 
970 PRMAN_INLINE
972 {
973  return (fields.bits.U != 0);
974 }
975 
976 PRMAN_INLINE
977 unsigned RixBXLobeTraits::Serialize() const
978 {
979  return fields.us;
980 }
981 
982 PRMAN_INLINE
983 RixBXLobeTraits const &
985 {
986  /* Bitwise AND all fields. We write one instruction that has the
987  * same effect as performing the following assignments:
988 
989  fields.bits.discreteSubset &= rhs.fields.bits.discreteSubset;
990  fields.bits.reflectSubset &= rhs.fields.bits.reflectSubset;
991  fields.bits.transmitSubset &= rhs.fields.bits.transmitSubset;
992  fields.bits.continuationSubset &= rhs.fields.bits.continuationSubset;
993  fields.bits.D &= rhs.fields.bits.D;
994  fields.bits.S &= rhs.fields.bits.S;
995  fields.bits.U &= rhs.fields.bits.U;
996  fields.bits.maxspeculardepth &= rhs.fields.bits.maxspeculardepth;
997  fields.bits.maxdiffusedepth &= rhs.fields.bits.maxdiffusedepth;
998  */
999 
1000  fields.us &= rhs.fields.us;
1001 
1002  return *this;
1003 }
1004 
1005 PRMAN_INLINE
1006 RixBXLobeTraits const &
1008 {
1009  /* Bitwise OR all fields. We write one instruction that has the
1010  * same effect as performing the following assignments:
1011 
1012  fields.bits.discreteSubset |= rhs.fields.bits.discreteSubset;
1013  fields.bits.reflectSubset |= rhs.fields.bits.reflectSubset;
1014  fields.bits.transmitSubset |= rhs.fields.bits.transmitSubset;
1015  fields.bits.continuationSubset |= rhs.fields.bits.continuationSubset;
1016  fields.bits.D |= rhs.fields.bits.D;
1017  fields.bits.S |= rhs.fields.bits.S;
1018  fields.bits.U |= rhs.fields.bits.U;
1019  fields.bits.maxspeculardepth |= rhs.fields.bits.maxspeculardepth;
1020  fields.bits.maxdiffusedepth |= rhs.fields.bits.maxdiffusedepth;
1021  */
1022 
1023  fields.us |= rhs.fields.us;
1024 
1025  return *this;
1026 }
1027 
1028 PRMAN_INLINE RixBXLobeTraits operator & (RixBXLobeTraits const &lhs,
1029  RixBXLobeTraits const &rhs)
1030 {
1031  /* Bitwise AND all fields. We write one instruction that has the
1032  * same effect as performing the following assignments:
1033 
1034  r.fields.bits.discreteSubset =
1035  lhs.fields.bits.discreteSubset & rhs.fields.bits.discreteSubset;
1036  r.fields.bits.reflectSubset =
1037  lhs.fields.bits.reflectSubset & rhs.fields.bits.reflectSubset;
1038  r.fields.bits.transmitSubset =
1039  lhs.fields.bits.transmitSubset & rhs.fields.bits.transmitSubset;
1040  r.fields.bits.continuationSubset =
1041  lhs.fields.bits.continuationSubset &
1042  rhs.fields.bits.continuationSubset;
1043  r.fields.bits.D = lhs.fields.bits.D & rhs.fields.bits.D;
1044  r.fields.bits.S = lhs.fields.bits.S & rhs.fields.bits.S;
1045  r.fields.bits.U = lhs.fields.bits.U & rhs.fields.bits.U;
1046  */
1047 
1048  RixBXLobeTraits r(lhs.Serialize() & rhs.Serialize());
1049  return r;
1050 }
1051 
1052 PRMAN_INLINE RixBXLobeTraits operator | (RixBXLobeTraits const &lhs,
1053  RixBXLobeTraits const &rhs)
1054 {
1055  /* Bitwise OR all fields. We write one instruction that has the
1056  * same effect as performing the following assignments:
1057 
1058  r.fields.bits.discreteSubset =
1059  lhs.fields.bits.discreteSubset | rhs.fields.bits.discreteSubset;
1060  r.fields.bits.reflectSubset =
1061  lhs.fields.bits.reflectSubset | rhs.fields.bits.reflectSubset;
1062  r.fields.bits.transmitSubset =
1063  lhs.fields.bits.transmitSubset | rhs.fields.bits.transmitSubset;
1064  r.fields.bits.continuationSubset =
1065  lhs.fields.bits.continuationSubset |
1066  rhs.fields.bits.continuationSubset;
1067  r.fields.bits.D = lhs.fields.bits.D | rhs.fields.bits.D;
1068  r.fields.bits.S = lhs.fields.bits.S | rhs.fields.bits.S;
1069  r.fields.bits.U = lhs.fields.bits.U | rhs.fields.bits.U;
1070  */
1071 
1072  RixBXLobeTraits r(lhs.Serialize() | rhs.Serialize());
1073  return r;
1074 }
1075 
1076 //
1077 // class RixBXActiveLobeWeights implementation
1078 //
1079 
1080 PRMAN_INLINE
1082  :
1083  m_offset(0),
1084  m_numDiffuseLobes(0),
1085  m_numSpecularLobes(0),
1086  m_numUserLobes(0)
1087 {
1088 }
1089 
1090 PRMAN_INLINE
1092  int numDiffuseLobes,
1093  int numSpecularLobes,
1094  int numUserLobes,
1095  RtColorRGB *diffuseLobes[],
1096  RtColorRGB *specularLobes[],
1097  RtColorRGB *userLobes[],
1098  unsigned char diffuseLpeIds[],
1099  unsigned char specularLpeIds[],
1100  unsigned char userLpeIds[],
1101  int offset)
1102  :
1103  m_offset(offset),
1104  m_lobeTraits(lobeTraits),
1105  m_numDiffuseLobes((unsigned char)numDiffuseLobes),
1106  m_numSpecularLobes((unsigned char)numSpecularLobes),
1107  m_numUserLobes((unsigned char)numUserLobes)
1108 {
1109  for (int i = 0; i < numDiffuseLobes; i++)
1110  {
1111  m_diffuseLobes[i] = diffuseLobes[i];
1112  m_diffuseLpeIds[i] = diffuseLpeIds[i];
1113  }
1114 
1115  for (int i = 0; i < numSpecularLobes; i++)
1116  {
1117  m_specularLobes[i] = specularLobes[i];
1118  m_specularLpeIds[i] = specularLpeIds[i];
1119  }
1120 
1121  for (int i = 0; i < numUserLobes; i++)
1122  {
1123  m_userLobes[i] = userLobes[i];
1124  m_userLpeIds[i] = userLpeIds[i];
1125  }
1126 }
1127 
1128 PRMAN_INLINE
1131  :
1132  m_offset(that.m_offset),
1133  m_lobeTraits(that.m_lobeTraits),
1134  m_numDiffuseLobes(that.m_numDiffuseLobes),
1135  m_numSpecularLobes(that.m_numSpecularLobes),
1136  m_numUserLobes(that.m_numUserLobes)
1137 {
1138  for (int i = 0; i < m_numDiffuseLobes; i++)
1139  {
1140  m_diffuseLobes[i] = that.m_diffuseLobes[i];
1141  m_diffuseLpeIds[i] = that.m_diffuseLpeIds[i];
1142  }
1143  for (int i = 0; i < m_numSpecularLobes; i++)
1144  {
1145  m_specularLobes[i] = that.m_specularLobes[i];
1146  m_specularLpeIds[i] = that.m_specularLpeIds[i];
1147  }
1148  for (int i = 0; i < m_numUserLobes; i++)
1149  {
1150  m_userLobes[i] = that.m_userLobes[i];
1151  m_userLpeIds[i] = that.m_userLpeIds[i];
1152  }
1153 }
1154 
1155 PRMAN_INLINE
1158 {
1159  m_offset = that.m_offset;
1160  m_lobeTraits = that.m_lobeTraits;
1161  m_numDiffuseLobes = that.m_numDiffuseLobes;
1162  m_numSpecularLobes = that.m_numSpecularLobes;
1163  m_numUserLobes = that.m_numUserLobes;
1164 
1165  for (int i = 0; i < m_numDiffuseLobes; i++)
1166  {
1167  m_diffuseLobes[i] = that.m_diffuseLobes[i];
1168  m_diffuseLpeIds[i] = that.m_diffuseLpeIds[i];
1169  }
1170  for (int i = 0; i < m_numSpecularLobes; i++)
1171  {
1172  m_specularLobes[i] = that.m_specularLobes[i];
1173  m_specularLpeIds[i] = that.m_specularLpeIds[i];
1174  }
1175  for (int i = 0; i < m_numUserLobes; i++)
1176  {
1177  m_userLobes[i] = that.m_userLobes[i];
1178  m_userLpeIds[i] = that.m_userLpeIds[i];
1179  }
1180 
1181  return *this;
1182 }
1183 
1184 PRMAN_INLINE
1185 int RixBXActiveLobeWeights::GetOffset() const
1186 {
1187  return m_offset;
1188 }
1189 
1190 PRMAN_INLINE
1191 void RixBXActiveLobeWeights::SetOffset(int offset)
1192 {
1193  m_offset = offset;
1194 }
1195 
1196 PRMAN_INLINE
1197 RixBXLobeTraits RixBXActiveLobeWeights::GetLobeTraits() const
1198 {
1199  return m_lobeTraits;
1200 }
1201 
1202 PRMAN_INLINE
1203 void RixBXActiveLobeWeights::SetLobeTraits(RixBXLobeTraits lobes)
1204 {
1205  m_lobeTraits = lobes;
1206 }
1207 
1208 PRMAN_INLINE unsigned char
1209 RixBXActiveLobeWeights::GetNumDiffuseLobes() const
1210 {
1211  return m_numDiffuseLobes;
1212 }
1213 
1214 PRMAN_INLINE unsigned char
1215 RixBXActiveLobeWeights::GetNumSpecularLobes() const
1216 {
1217  return m_numSpecularLobes;
1218 }
1219 
1220 PRMAN_INLINE unsigned char
1221 RixBXActiveLobeWeights::GetNumUserLobes() const
1222 {
1223  return m_numUserLobes;
1224 }
1225 
1226 PRMAN_INLINE RtColorRGB const *
1227 RixBXActiveLobeWeights::GetDiffuseLobe(int i) const
1228 {
1229  return m_diffuseLobes[i] + m_offset;
1230 }
1231 
1232 PRMAN_INLINE RtColorRGB const *
1233 RixBXActiveLobeWeights::GetSpecularLobe(int i) const
1234 {
1235  return m_specularLobes[i] + m_offset;
1236 }
1237 
1238 PRMAN_INLINE RtColorRGB const *
1239 RixBXActiveLobeWeights::GetUserLobe(int i) const
1240 {
1241  return m_userLobes[i] + m_offset;
1242 }
1243 
1244 PRMAN_INLINE RtColorRGB *
1245 RixBXActiveLobeWeights::GetDiffuseLobe(int i)
1246 {
1247  return m_diffuseLobes[i] + m_offset;
1248 }
1249 
1250 PRMAN_INLINE RtColorRGB *
1251 RixBXActiveLobeWeights::GetSpecularLobe(int i)
1252 {
1253  return m_specularLobes[i] + m_offset;
1254 }
1255 
1256 PRMAN_INLINE RtColorRGB *
1257 RixBXActiveLobeWeights::GetUserLobe(int i)
1258 {
1259  return m_userLobes[i] + m_offset;
1260 }
1261 
1262 PRMAN_INLINE unsigned char
1263 RixBXActiveLobeWeights::GetDiffuseLpeId(int i) const
1264 {
1265  return m_diffuseLpeIds[i];
1266 }
1267 
1268 PRMAN_INLINE unsigned char
1269 RixBXActiveLobeWeights::GetSpecularLpeId(int i) const
1270 {
1271  return m_specularLpeIds[i];
1272 }
1273 
1274 PRMAN_INLINE unsigned char
1275 RixBXActiveLobeWeights::GetUserLpeId(int i) const
1276 {
1277  return m_userLpeIds[i];
1278 }
1279 
1280 PRMAN_INLINE void
1281 RixBXActiveLobeWeights::ClearAllDiffuseLobes()
1282 {
1283  m_numDiffuseLobes = 0;
1284  // Removes all diffuse lobes from traits
1285  m_lobeTraits &= (k_RixBXTraitsAllSpecular | k_RixBXTraitsAllUser);
1286 }
1287 
1288 PRMAN_INLINE void
1289 RixBXActiveLobeWeights::ClearAllSpecularLobes()
1290 {
1291  m_numSpecularLobes = 0;
1292  // Removes all specular lobes from traits
1293  m_lobeTraits &= (k_RixBXTraitsAllDiffuse | k_RixBXTraitsAllUser);
1294 }
1295 
1296 PRMAN_INLINE void
1297 RixBXActiveLobeWeights::ClearAllUserLobes()
1298 {
1299  m_numUserLobes = 0;
1300  // Removes all user lobes from traits
1301  m_lobeTraits &= (k_RixBXTraitsAllDiffuse | k_RixBXTraitsAllSpecular);
1302 }
1303 
1304 PRMAN_INLINE
1305 RtColorRGB RixBXActiveLobeWeights::SumAtIndex(int index,
1306  bool includeUserLobes) const
1307 {
1308  RtColorRGB sum(0.0f);
1309 
1310  int idx = m_offset + index;
1311  for (int i = 0; i < m_numDiffuseLobes; i++)
1312  sum += m_diffuseLobes[i][idx];
1313  for (int i = 0; i < m_numSpecularLobes; i++)
1314  sum += m_specularLobes[i][idx];
1315 
1316  if (includeUserLobes)
1317  {
1318  for (int i = 0; i < m_numUserLobes; i++)
1319  sum += m_userLobes[i][idx];
1320  }
1321 
1322  return sum;
1323 }
1324 
1325 PRMAN_INLINE
1326 void RixBXActiveLobeWeights::MultiplyByWeightAtIndex
1327  (int index, float weight, bool includeUserLobes)
1328 {
1329  int idx = m_offset + index;
1330  for (int i = 0; i < m_numDiffuseLobes; i++)
1331  m_diffuseLobes[i][idx] *= weight;
1332  for (int i = 0; i < m_numSpecularLobes; i++)
1333  m_specularLobes[i][idx] *= weight;
1334 
1335  if (includeUserLobes)
1336  {
1337  for (int i = 0; i < m_numUserLobes; i++)
1338  m_userLobes[i][idx] *= weight;
1339  }
1340 }
1341 
1342 PRMAN_INLINE
1343 void RixBXActiveLobeWeights::MultiplyByWeightAtIndex
1344  (int index, RtColorRGB const &weight, bool includeUserLobes)
1345 {
1346  int idx = m_offset + index;
1347  for (int i = 0; i < m_numDiffuseLobes; i++)
1348  m_diffuseLobes[i][idx] *= weight;
1349  for (int i = 0; i < m_numSpecularLobes; i++)
1350  m_specularLobes[i][idx] *= weight;
1351 
1352  if (includeUserLobes)
1353  {
1354  for (int i = 0; i < m_numUserLobes; i++)
1355  m_userLobes[i][idx] *= weight;
1356  }
1357 }
1358 
1359 //
1360 // class RixBXLobeWeights implementation
1361 //
1362 
1363 PRMAN_INLINE
1365  :
1366  m_numPoints(0),
1367  m_offset(0),
1368  m_numDiffuseLobes(0),
1369  m_numSpecularLobes(0),
1370  m_numUserLobes(0)
1371 {
1372 }
1373 
1374 PRMAN_INLINE
1376  int numDiffuseLobes,
1377  int numSpecularLobes,
1378  int numUserLobes,
1379  RtColorRGB *diffuseLobes[],
1380  RtColorRGB *specularLobes[],
1381  RtColorRGB *userLobes[],
1382  int offset)
1383  :
1384  m_numPoints(numPoints),
1385  m_offset(offset),
1386  m_numDiffuseLobes((unsigned char)numDiffuseLobes),
1387  m_numSpecularLobes((unsigned char)numSpecularLobes),
1388  m_numUserLobes((unsigned char)numUserLobes)
1389 {
1390  for (int i = 0; i < numDiffuseLobes; i++)
1391  m_diffuseLobes[i] = diffuseLobes[i];
1392 
1393  for (int i = 0; i < numSpecularLobes; i++)
1394  m_specularLobes[i] = specularLobes[i];
1395 
1396  for (int i = 0; i < numUserLobes; i++)
1397  m_userLobes[i] = userLobes[i];
1398 }
1399 
1400 PRMAN_INLINE
1402  :
1403  m_numPoints(that.m_numPoints),
1404  m_offset(that.m_offset),
1405  m_activeLobeTraits(that.m_activeLobeTraits),
1406  m_numDiffuseLobes(that.m_numDiffuseLobes),
1407  m_numSpecularLobes(that.m_numSpecularLobes),
1408  m_numUserLobes(that.m_numUserLobes)
1409 {
1410  for (int i = 0; i < m_numDiffuseLobes; i++)
1411  m_diffuseLobes[i] = that.m_diffuseLobes[i];
1412 
1413  for (int i = 0; i < m_numSpecularLobes; i++)
1414  m_specularLobes[i] = that.m_specularLobes[i];
1415 
1416  for (int i = 0; i < m_numUserLobes; i++)
1417  m_userLobes[i] = that.m_userLobes[i];
1418 }
1419 
1420 PRMAN_INLINE
1423 {
1424  m_numPoints = that.m_numPoints;
1425  m_offset = that.m_offset;
1426  m_activeLobeTraits = that.m_activeLobeTraits;
1427  m_numDiffuseLobes = that.m_numDiffuseLobes;
1428  m_numSpecularLobes = that.m_numSpecularLobes;
1429  m_numUserLobes = that.m_numUserLobes;
1430 
1431  for (int i = 0; i < m_numDiffuseLobes; i++)
1432  m_diffuseLobes[i] = that.m_diffuseLobes[i];
1433 
1434  for (int i = 0; i < m_numSpecularLobes; i++)
1435  m_specularLobes[i] = that.m_specularLobes[i];
1436 
1437  for (int i = 0; i < m_numUserLobes; i++)
1438  m_userLobes[i] = that.m_userLobes[i];
1439 
1440  return *this;
1441 }
1442 
1443 PRMAN_INLINE RtColorRGB const *
1444 RixBXLobeWeights::GetDiffuseLobe(int i) const
1445 {
1446  return m_diffuseLobes[i] + m_offset;
1447 }
1448 
1449 PRMAN_INLINE RtColorRGB const *
1450 RixBXLobeWeights::GetSpecularLobe(int i) const
1451 {
1452  return m_specularLobes[i] + m_offset;
1453 }
1454 
1455 PRMAN_INLINE RtColorRGB const *
1456 RixBXLobeWeights::GetUserLobe(int i) const
1457 {
1458  return m_userLobes[i] + m_offset;
1459 }
1460 
1461 PRMAN_INLINE RtColorRGB *
1462 RixBXLobeWeights::GetDiffuseLobe(int i)
1463 {
1464  return m_diffuseLobes[i] + m_offset;
1465 }
1466 
1467 PRMAN_INLINE RtColorRGB *
1468 RixBXLobeWeights::GetSpecularLobe(int i)
1469 {
1470  return m_specularLobes[i] + m_offset;
1471 }
1472 
1473 PRMAN_INLINE RtColorRGB *
1474 RixBXLobeWeights::GetUserLobe(int i)
1475 {
1476  return m_userLobes[i] + m_offset;
1477 }
1478 
1479 PRMAN_INLINE
1480 int RixBXLobeWeights::GetNumPoints() const { return m_numPoints; }
1481 
1482 PRMAN_INLINE
1483 void RixBXLobeWeights::SetNumPoints(int numPoints) { m_numPoints = numPoints; }
1484 
1485 PRMAN_INLINE
1486 int RixBXLobeWeights::GetOffset() const { return m_offset; }
1487 
1488 PRMAN_INLINE
1489 void RixBXLobeWeights::SetOffset(int offset) { m_offset = offset; }
1490 
1491 PRMAN_INLINE
1492 RixBXLobeTraits RixBXLobeWeights::GetActiveLobeTraits() const
1493 {
1494  return m_activeLobeTraits;
1495 }
1496 
1497 PRMAN_INLINE
1498 void RixBXLobeWeights::SetActiveLobeTraits(RixBXLobeTraits lobes)
1499 {
1500  m_activeLobeTraits = lobes;
1501 }
1502 
1503 PRMAN_INLINE
1504 void RixBXLobeWeights::AddActiveLobeTraits(RixBXLobeTraits lobes)
1505 {
1506  m_activeLobeTraits |= lobes;
1507 }
1508 
1509 PRMAN_INLINE
1510 int RixBXLobeWeights::GetNumDiffuseLobes() const
1511 {
1512  return m_numDiffuseLobes;
1513 }
1514 
1515 PRMAN_INLINE
1516 int RixBXLobeWeights::GetNumSpecularLobes() const
1517 {
1518  return m_numSpecularLobes;
1519 }
1520 
1521 PRMAN_INLINE
1522 int RixBXLobeWeights::GetNumUserLobes() const
1523 {
1524  return m_numUserLobes;
1525 }
1526 
1527 PRMAN_INLINE
1529  bool doInitializeWeights)
1530 {
1531  if (lobeSampled.GetUser())
1532  {
1533  RixBXLobeTraits traits(lobeSampled);
1534  int lpeId = lobeSampled.GetLpeId();
1535  if (lpeId < m_numUserLobes)
1536  {
1537  RtColorRGB *p = m_userLobes[lpeId];
1538  if (!(m_activeLobeTraits.GetUser() & traits.GetUser()))
1539  {
1540  m_activeLobeTraits |= traits;
1541  if (doInitializeWeights)
1542  memset(p, 0, m_numPoints * sizeof(RtColorRGB));
1543  }
1544  return p + m_offset;
1545  }
1546  }
1547  else if (lobeSampled.GetDiffuse())
1548  {
1549  RixBXLobeTraits traits(lobeSampled);
1550  int lpeId = lobeSampled.GetLpeId();
1551  if (lpeId < m_numDiffuseLobes)
1552  {
1553  RtColorRGB *p = m_diffuseLobes[lpeId];
1554  if (!(m_activeLobeTraits.GetDiffuse() & traits.GetDiffuse()))
1555  {
1556  m_activeLobeTraits |= traits;
1557  if (doInitializeWeights)
1558  memset(p, 0, m_numPoints * sizeof(RtColorRGB));
1559  }
1560  return p + m_offset;
1561  }
1562  }
1563  else if (lobeSampled.GetSpecular())
1564  {
1565  RixBXLobeTraits traits(lobeSampled);
1566  int lpeId = lobeSampled.GetLpeId();
1567  if (lpeId < m_numSpecularLobes)
1568  {
1569  RtColorRGB *p = m_specularLobes[lpeId];
1570  if (!(m_activeLobeTraits.GetSpecular() & traits.GetSpecular()))
1571  {
1572  m_activeLobeTraits |= traits;
1573  if (doInitializeWeights)
1574  memset(p, 0, m_numPoints * sizeof(RtColorRGB));
1575  }
1576  return p + m_offset;
1577  }
1578  }
1579  return NULL;
1580 }
1581 
1582 PRMAN_INLINE
1584 {
1585  r.m_numDiffuseLobes = r.m_numSpecularLobes = r.m_numUserLobes = 0;
1586  r.m_lobeTraits = m_activeLobeTraits;
1587  r.m_offset = m_offset;
1588 
1589  RixBXLobeTraits lobes = m_activeLobeTraits;
1590 
1591  int ndiff = m_numDiffuseLobes;
1592  for (int lpeId = 0, bit = 1; lpeId < ndiff; lpeId++, bit <<= 1)
1593  {
1594  if (lobes.GetDiffuse() & bit)
1595  {
1596  r.m_diffuseLobes[r.m_numDiffuseLobes] = m_diffuseLobes[lpeId];
1597  r.m_diffuseLpeIds[r.m_numDiffuseLobes] = (unsigned char)lpeId;
1598  r.m_numDiffuseLobes++;
1599  }
1600  }
1601  int nspec = m_numSpecularLobes;
1602  for (int lpeId = 0, bit = 1; lpeId < nspec; lpeId++, bit <<= 1)
1603  {
1604  if (lobes.GetSpecular() & bit)
1605  {
1606  r.m_specularLobes[r.m_numSpecularLobes] =
1607  m_specularLobes[lpeId];
1608  r.m_specularLpeIds[r.m_numSpecularLobes] = (unsigned char)lpeId;
1609  r.m_numSpecularLobes++;
1610  }
1611  }
1612  int nuser = m_numUserLobes;
1613  for (int lpeId = 0, bit = 1; lpeId < nuser; lpeId++, bit <<= 1)
1614  {
1615  if (lobes.GetUser() & bit)
1616  {
1617  r.m_userLobes[r.m_numUserLobes] =
1618  m_userLobes[lpeId];
1619  r.m_userLpeIds[r.m_numUserLobes] = (unsigned char)lpeId;
1620  r.m_numUserLobes++;
1621  }
1622  }
1623 }
1624 
1625 PRMAN_INLINE
1628  RixBXActiveLobeWeights &activeLhs,
1629  RixBXActiveLobeWeights &activeRhs)
1630 {
1631  int numDiffuseLobes = 0;
1632  int numSpecularLobes = 0;
1633  int numUserLobes = 0;
1634 
1635  RixBXLobeTraits lobes = (m_activeLobeTraits & rhs.m_activeLobeTraits);
1636 
1637  int ndiff = std::min(m_numDiffuseLobes, rhs.m_numDiffuseLobes);
1638  for (int lpeId = 0, bit = 1; lpeId < ndiff; lpeId++, bit <<= 1)
1639  {
1640  if (lobes.GetDiffuse() & bit)
1641  {
1642  activeLhs.m_diffuseLobes[numDiffuseLobes] =
1643  m_diffuseLobes[lpeId];
1644  activeRhs.m_diffuseLobes[numDiffuseLobes] =
1645  rhs.m_diffuseLobes[lpeId];
1646  activeLhs.m_diffuseLpeIds[numDiffuseLobes] = (unsigned char)lpeId;
1647  activeRhs.m_diffuseLpeIds[numDiffuseLobes] = (unsigned char)lpeId;
1648  numDiffuseLobes++;
1649  }
1650  }
1651  int nspec = std::min(m_numSpecularLobes, rhs.m_numSpecularLobes);
1652  for (int lpeId = 0, bit = 1; lpeId < nspec; lpeId++, bit <<= 1)
1653  {
1654  if (lobes.GetSpecular() & bit)
1655  {
1656  activeLhs.m_specularLobes[numSpecularLobes] =
1657  m_specularLobes[lpeId];
1658  activeRhs.m_specularLobes[numSpecularLobes] =
1659  rhs.m_specularLobes[lpeId];
1660  activeLhs.m_specularLpeIds[numSpecularLobes] = (unsigned char)lpeId;
1661  activeRhs.m_specularLpeIds[numSpecularLobes] = (unsigned char)lpeId;
1662  numSpecularLobes++;
1663  }
1664  }
1665  int nuser = std::min(m_numUserLobes, rhs.m_numUserLobes);
1666  for (int lpeId = 0, bit = 1; lpeId < nuser; lpeId++, bit <<= 1)
1667  {
1668  if (lobes.GetUser() & bit)
1669  {
1670  activeLhs.m_userLobes[numUserLobes] =
1671  m_userLobes[lpeId];
1672  activeRhs.m_userLobes[numUserLobes] =
1673  rhs.m_userLobes[lpeId];
1674  activeLhs.m_userLpeIds[numUserLobes] = (unsigned char)lpeId;
1675  activeRhs.m_userLpeIds[numUserLobes] = (unsigned char)lpeId;
1676  numUserLobes++;
1677  }
1678  }
1679 
1680  activeLhs.m_offset = m_offset;
1681  activeLhs.m_lobeTraits = lobes;
1682  activeLhs.m_numDiffuseLobes = (unsigned char)numDiffuseLobes;
1683  activeLhs.m_numSpecularLobes = (unsigned char)numSpecularLobes;
1684  activeLhs.m_numUserLobes = (unsigned char)numUserLobes;
1685 
1686  activeRhs.m_offset = rhs.m_offset;
1687  activeRhs.m_lobeTraits = lobes;
1688  activeRhs.m_numDiffuseLobes = (unsigned char)numDiffuseLobes;
1689  activeRhs.m_numSpecularLobes = (unsigned char)numSpecularLobes;
1690  activeRhs.m_numUserLobes = (unsigned char)numUserLobes;
1691 }
1692 
1693 PRMAN_INLINE
1694 void RixBXLobeWeights::CopyWeightAtIndex(int index,
1695  RixBXActiveLobeWeights const &src,
1696  bool includeUserLobes)
1697 {
1698  // Copy over just the active diffuse, specular, and user lobes in 'src'.
1699  int ndiff = src.GetNumDiffuseLobes();
1700  for (int i = 0; i < ndiff; i++)
1701  {
1702  int lpeId = src.GetDiffuseLpeId(i);
1703  GetDiffuseLobe(lpeId)[index] = src.GetDiffuseLobe(i)[index];
1704  }
1705 
1706  int nspec = src.GetNumSpecularLobes();
1707  for (int i = 0; i < nspec; i++)
1708  {
1709  int lpeId = src.GetSpecularLpeId(i);
1710  GetSpecularLobe(lpeId)[index] = src.GetSpecularLobe(i)[index];
1711  }
1712 
1713  if (includeUserLobes)
1714  {
1715  int nuser = src.GetNumUserLobes();
1716  for (int i = 0; i < nuser; i++)
1717  {
1718  int lpeId = src.GetUserLpeId(i);
1719  GetUserLobe(lpeId)[index] = src.GetUserLobe(i)[index];
1720  }
1721  }
1722 }
1723 
1724 PRMAN_INLINE
1725 void RixBXLobeWeights::AddWeightAtIndex(int index,
1726  RixBXActiveLobeWeights const &src,
1727  bool includeUserLobes)
1728 {
1729  // Add in just the active diffuse, specular, and user lobes in 'src'.
1730  int ndiff = src.GetNumDiffuseLobes();
1731  for (int i = 0; i < ndiff; i++)
1732  {
1733  int lpeId = src.GetDiffuseLpeId(i);
1734  GetDiffuseLobe(lpeId)[index] += src.GetDiffuseLobe(i)[index];
1735  }
1736 
1737  int nspec = src.GetNumSpecularLobes();
1738  for (int i = 0; i < nspec; i++)
1739  {
1740  int lpeId = src.GetSpecularLpeId(i);
1741  GetSpecularLobe(lpeId)[index] += src.GetSpecularLobe(i)[index];
1742  }
1743 
1744  if (includeUserLobes)
1745  {
1746  int nuser = src.GetNumUserLobes();
1747  for (int i = 0; i < nuser; i++)
1748  {
1749  int lpeId = src.GetUserLpeId(i);
1750  GetUserLobe(lpeId)[index] += src.GetUserLobe(i)[index];
1751  }
1752  }
1753 }
1754 
1755 #endif