1 //-*****************************************************************************
2 //
3 // Copyright (c) 2009-2014,
4 //  Sony Pictures Imageworks Inc. and
5 //  Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd.
6 //
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are
11 // met:
12 // *       Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // *       Redistributions in binary form must reproduce the above
15 // copyright notice, this list of conditions and the following disclaimer
16 // in the documentation and/or other materials provided with the
17 // distribution.
18 // *       Neither the name of Sony Pictures Imageworks, nor
19 // Industrial Light & Magic, nor the names of their contributors may be used
20 // to endorse or promote products derived from this software without specific
21 // prior written permission.
22 //
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 //
35 //-*****************************************************************************
36 
37 #ifndef Alembic_AbcGeom_IGeomParam_h
38 #define Alembic_AbcGeom_IGeomParam_h
39 
40 #include <Alembic/AbcGeom/Foundation.h>
41 #include <Alembic/AbcGeom/GeometryScope.h>
42 
43 namespace Alembic {
44 namespace AbcGeom {
45 namespace ALEMBIC_VERSION_NS {
46 
47 //-*****************************************************************************
48 template <class TRAITS>
49 class ITypedGeomParam
50 {
51 public:
52     typedef typename TRAITS::value_type value_type;
53     typedef Abc::ITypedArrayProperty<TRAITS> prop_type;
54 
55     class Sample
56     {
57     public:
58         typedef Sample this_type;
59         typedef Alembic::Util::shared_ptr< Abc::TypedArraySample<TRAITS> > samp_ptr_type;
60 
Sample()61         Sample()
62         {}
63 
getIndices()64         Abc::UInt32ArraySamplePtr getIndices() const { return m_indices; }
getVals()65         samp_ptr_type getVals() const { return m_vals; }
getScope()66         GeometryScope getScope() const { return m_scope; }
isIndexed()67         bool isIndexed() const { return m_isIndexed; }
68 
reset()69         void reset()
70         {
71             m_vals.reset();
72             m_indices.reset();
73             m_scope = kUnknownScope;
74             m_isIndexed = false;
75         }
76 
valid()77         bool valid() const { return m_vals.get() != NULL; }
78 
79         ALEMBIC_OPERATOR_BOOL( valid() );
80 
81     protected:
82         friend class ITypedGeomParam<TRAITS>;
83         samp_ptr_type m_vals;
84         Abc::UInt32ArraySamplePtr m_indices;
85         GeometryScope m_scope;
86         bool m_isIndexed;
87     };
88 
89     //-*************************************************************************
90     typedef ITypedGeomParam<TRAITS> this_type;
91     typedef typename this_type::Sample sample_type;
92 
getInterpretation()93     static const char * getInterpretation()
94     {
95         return TRAITS::interpretation();
96     }
97 
98     static bool matches( const AbcA::PropertyHeader &iHeader,
99                          SchemaInterpMatching iMatching = kStrictMatching )
100     {
101         if ( iHeader.isCompound() )
102         {
103             return ( iHeader.getMetaData().get( "podName" ) ==
104                     Alembic::Util::PODName( TRAITS::dataType().getPod() ) &&
105                     ( std::string() == getInterpretation() ||
106                       atoi(
107                         iHeader.getMetaData().get( "podExtent" ).c_str() ) ==
108                      TRAITS::dataType().getExtent() ) ) &&
109                     prop_type::matches( iHeader.getMetaData(), iMatching );
110         }
111         else if ( iHeader.isArray() )
112         {
113             return prop_type::matches( iHeader, iMatching );
114         }
115 
116         return false;
117     }
118 
ITypedGeomParam()119     ITypedGeomParam() {m_isIndexed = false;}
120 
121     template <class CPROP>
122     ITypedGeomParam( CPROP iParent,
123                      const std::string &iName,
124                      const Abc::Argument &iArg0 = Abc::Argument(),
125                      const Abc::Argument &iArg1 = Abc::Argument() );
126 
127     template <class PROP>
128     ITypedGeomParam( PROP iThis,
129                      WrapExistingFlag iWrapFlag,
130                      const Abc::Argument &iArg0 = Abc::Argument(),
131                      const Abc::Argument &iArg1 = Abc::Argument() );
132 
133     void getIndexed( sample_type &oSamp,
134                      const Abc::ISampleSelector &iSS = Abc::ISampleSelector() ) const;
135 
136     void getExpanded( sample_type &oSamp,
137                       const Abc::ISampleSelector &iSS = Abc::ISampleSelector() ) const;
138 
139     sample_type getIndexedValue( const Abc::ISampleSelector &iSS = \
140                                  Abc::ISampleSelector() ) const
141     {
142         sample_type ret;
143         getIndexed( ret, iSS );
144         return ret;
145     }
146 
147     sample_type getExpandedValue( const Abc::ISampleSelector &iSS = \
148                                   Abc::ISampleSelector() ) const
149     {
150         sample_type ret;
151         getExpanded( ret, iSS );
152         return ret;
153     }
154 
155     size_t getNumSamples() const;
156 
getDataType()157     AbcA::DataType getDataType() const { return TRAITS::dataType(); }
158 
getArrayExtent()159     size_t getArrayExtent() const
160     {
161         std::string e = m_valProp.getMetaData().get( "arrayExtent" );
162         if ( e == "" ) { return 1; }
163         else { return atoi( e.c_str() ); }
164     }
165 
isIndexed()166     bool isIndexed() const { return m_isIndexed; }
167 
getScope()168     GeometryScope getScope() const
169     { return GetGeometryScope( m_valProp.getMetaData() ); }
170 
171     AbcA::TimeSamplingPtr getTimeSampling() const;
172 
173     const std::string &getName() const;
174 
175     Abc::ICompoundProperty getParent() const;
176 
177     const AbcA::PropertyHeader &getHeader() const;
178 
179     const AbcA::MetaData &getMetaData() const;
180 
181     bool isConstant() const;
182 
reset()183     void reset()
184     {
185         m_valProp.reset();
186         m_indicesProperty.reset();
187         m_cprop.reset();
188         m_isIndexed = false;
189     }
190 
valid()191     bool valid() const
192     {
193         return ( m_valProp.valid()
194                  && ( ( ! m_cprop ) || m_indicesProperty ) );
195     }
196 
197     ALEMBIC_OPERATOR_BOOL( this_type::valid() );
198 
getValueProperty()199     prop_type getValueProperty() { return m_valProp; }
200 
getIndexProperty()201     Abc::IUInt32ArrayProperty getIndexProperty() { return m_indicesProperty; }
202 
203 private:
getErrorHandler()204     Abc::ErrorHandler &getErrorHandler() const
205     { return m_valProp.getErrorHandler(); }
206 
207 protected:
208     prop_type m_valProp;
209 
210     // if the GeomParam is not indexed, these will not exist.
211     Abc::IUInt32ArrayProperty m_indicesProperty;
212     Abc::ICompoundProperty m_cprop;
213 
214     bool m_isIndexed;
215 };
216 
217 //-*****************************************************************************
218 // TEMPLATED METHODS AND CONSTRUCTORS
219 //-*****************************************************************************
220 template <class TRAITS>
221 template <class CPROP>
ITypedGeomParam(CPROP iParent,const std::string & iName,const Abc::Argument & iArg0,const Abc::Argument & iArg1)222 ITypedGeomParam<TRAITS>::ITypedGeomParam( CPROP iParent,
223                                           const std::string &iName,
224                                           const Abc::Argument &iArg0,
225                                           const Abc::Argument &iArg1 )
226 {
227     Arguments args( GetErrorHandlerPolicy( iParent ) );
228     iArg0.setInto( args );
229     iArg1.setInto( args );
230 
231     getErrorHandler().setPolicy( args.getErrorHandlerPolicy() );
232 
233     ALEMBIC_ABC_SAFE_CALL_BEGIN( "ITypedGeomParam::ITypedGeomParam()" );
234 
235     AbcA::CompoundPropertyReaderPtr parent =
236         GetCompoundPropertyReaderPtr( iParent );
237     ABCA_ASSERT( parent != NULL,
238                  "NULL CompoundPropertyReader passed into "
239                  << "ITypedGeomParam ctor" );
240 
241     const AbcA::PropertyHeader *pheader =
242         parent->getPropertyHeader( iName );
243     ABCA_ASSERT( pheader != NULL,
244                  "Nonexistent GeomParam: " << iName );
245 
246     if ( pheader->isCompound() )
247     {
248         // we're indexed
249         m_cprop = ICompoundProperty( iParent, iName,
250                                      args.getErrorHandlerPolicy() );
251         m_indicesProperty = IUInt32ArrayProperty( m_cprop, ".indices", iArg0,
252                                                   iArg1 );
253         m_valProp = ITypedArrayProperty<TRAITS>( m_cprop, ".vals", iArg0,
254                                                  iArg1 );
255         m_isIndexed = true;
256     }
257     else if ( pheader->isArray() )
258     {
259         // not indexed
260         m_valProp = ITypedArrayProperty<TRAITS>( iParent, iName, iArg0,
261                                                  iArg1 );
262         m_isIndexed = false;
263     }
264     else
265     {
266         ABCA_ASSERT( false, "Invalid ITypedGeomParam: " << iName );
267     }
268 
269     ALEMBIC_ABC_SAFE_CALL_END();
270 }
271 
272 //-*****************************************************************************
273 template <class TRAITS>
274 template <class PROP>
ITypedGeomParam(PROP iThis,WrapExistingFlag iWrapFlag,const Abc::Argument & iArg0,const Abc::Argument & iArg1)275 ITypedGeomParam<TRAITS>::ITypedGeomParam( PROP iThis,
276                                           WrapExistingFlag iWrapFlag,
277                                           const Abc::Argument &iArg0,
278                                           const Abc::Argument &iArg1 )
279 {
280     Arguments args( GetErrorHandlerPolicy( iThis ) );
281     iArg0.setInto( args );
282     iArg1.setInto( args );
283 
284     getErrorHandler().setPolicy( args.getErrorHandlerPolicy() );
285 
286     ALEMBIC_ABC_SAFE_CALL_BEGIN( "ITypedGeomParam::ITypedGeomParam( wrap )" );
287 
288     const AbcA::PropertyHeader &ph = iThis.getHeader();
289 
290     ABCA_ASSERT( matches( ph,
291                           Abc::GetSchemaInterpMatching( iArg0, iArg1 ) ),
292                  "Property " << ph.getName() << " is not an "
293                  << "ITypedGeomParam" );
294 
295     ABCA_ASSERT( ! ph.isScalar(), "Property " << ph.getName()
296                  << " cannot be an ITypedGeomParam" );
297 
298     if ( ph.isCompound() )
299     {
300         // we're indexed
301         m_cprop = ICompoundProperty( iThis, iWrapFlag, iArg0, iArg1 );
302         m_indicesProperty = IUInt32ArrayProperty( m_cprop, ".indices", iArg0,
303                                                   iArg1 );
304         m_valProp = ITypedArrayProperty<TRAITS>( m_cprop, ".vals", iArg0,
305                                                  iArg1 );
306         m_isIndexed = true;
307     }
308     else
309     {
310         // not indexed
311         m_valProp = ITypedArrayProperty<TRAITS>( iThis, iWrapFlag, iArg0,
312                                                  iArg1 );
313         m_isIndexed = false;
314     }
315 
316     ALEMBIC_ABC_SAFE_CALL_END_RESET();
317 }
318 
319 //-*****************************************************************************
320 template <class TRAITS>
321 void
getIndexed(typename ITypedGeomParam<TRAITS>::Sample & oSamp,const Abc::ISampleSelector & iSS)322 ITypedGeomParam<TRAITS>::getIndexed( typename ITypedGeomParam<TRAITS>::Sample &oSamp,
323                                      const Abc::ISampleSelector &iSS ) const
324 {
325     m_valProp.get( oSamp.m_vals, iSS );
326     if ( m_indicesProperty ) { m_indicesProperty.get( oSamp.m_indices, iSS ); }
327     else
328     {
329         uint32_t size = static_cast< uint32_t > ( oSamp.m_vals->size() );
330 
331         uint32_t *v = new uint32_t[size];
332 
333         for ( uint32_t i = 0 ; i < size ; ++i )
334         {
335             v[i] = i;
336         }
337 
338         const Alembic::Util::Dimensions dims( size );
339 
340         oSamp.m_indices.reset( new Abc::UInt32ArraySample( v, dims ),
341                                AbcA::TArrayDeleter<uint32_t>() );
342     }
343 
344     oSamp.m_scope = this->getScope();
345     oSamp.m_isIndexed = m_isIndexed;
346 }
347 
348 
349 //-*****************************************************************************
350 template <class TRAITS>
351 void
getExpanded(typename ITypedGeomParam<TRAITS>::Sample & oSamp,const Abc::ISampleSelector & iSS)352 ITypedGeomParam<TRAITS>::getExpanded( typename ITypedGeomParam<TRAITS>::Sample &oSamp,
353                                       const Abc::ISampleSelector &iSS ) const
354 {
355     oSamp.m_scope = this->getScope();
356     oSamp.m_isIndexed = m_isIndexed;
357 
358     if ( ! m_indicesProperty )
359     {
360         m_valProp.get( oSamp.m_vals, iSS );
361     }
362     else
363     {
364         Abc::UInt32ArraySamplePtr idxPtr = m_indicesProperty.getValue( iSS );
365 
366         size_t size = idxPtr->size();
367 
368         // no indices?  just return what we have in our values
369         if (size == 0)
370         {
371             m_valProp.get( oSamp.m_vals, iSS );
372             return;
373         }
374 
375         Alembic::Util::shared_ptr< Abc::TypedArraySample<TRAITS> > valPtr = \
376             m_valProp.getValue( iSS );
377 
378         typename TRAITS::value_type *v = new typename TRAITS::value_type[size];
379 
380         for ( size_t i = 0 ; i < size ; ++i )
381         {
382             v[i] = (*valPtr)[ (*idxPtr)[i] ];
383         }
384 
385         // NOTE: we could create an ArraySampleKey and insert this into the
386         // cache.  If it were in the cache, we'd return the shared pointer
387         // from there and call delete[] on v, thus preventing potentially
388         // unbounded heap growth.  We should probably do this, but for now,
389         // we'll assume that we don't have too many of these, and we're not
390         // tightly memory-constrained. Ha!
391 
392         const Alembic::Util::Dimensions dims( size );
393 
394         oSamp.m_vals.reset( new Abc::TypedArraySample<TRAITS>( v, dims ),
395                             AbcA::TArrayDeleter<typename TRAITS::value_type>());
396     }
397 
398 }
399 
400 //-*****************************************************************************
401 template <class TRAITS>
getNumSamples()402 size_t ITypedGeomParam<TRAITS>::getNumSamples() const
403 {
404     ALEMBIC_ABC_SAFE_CALL_BEGIN( "ITypedGeomParam::getNumSamples()" );
405 
406     if ( m_isIndexed )
407     {
408         return std::max( m_indicesProperty.getNumSamples(),
409                          m_valProp.getNumSamples() );
410     }
411     else
412     {
413         if ( m_valProp ) { return m_valProp.getNumSamples(); }
414         else { return 0; }
415     }
416 
417     ALEMBIC_ABC_SAFE_CALL_END();
418 
419     return 0;
420 }
421 
422 //-*****************************************************************************
423 template <class TRAITS>
isConstant()424 bool ITypedGeomParam<TRAITS>::isConstant() const
425 {
426     ALEMBIC_ABC_SAFE_CALL_BEGIN( "ITypedGeomParam::isConstant()" );
427 
428     if ( m_isIndexed )
429     {
430         return m_valProp.isConstant() && m_indicesProperty.isConstant();
431     }
432     else
433     {
434         return m_valProp.isConstant();
435     }
436 
437     ALEMBIC_ABC_SAFE_CALL_END();
438 
439     return false;
440 }
441 
442 namespace {
443     const std::string g_emptyStr;
444 }
445 //-*****************************************************************************
446 template <class TRAITS>
getName()447 const std::string &ITypedGeomParam<TRAITS>::getName() const
448 {
449     ALEMBIC_ABC_SAFE_CALL_BEGIN( "ITypedGeomParam::getName()" );
450 
451     if ( m_isIndexed ) { return m_cprop.getName(); }
452     else { return m_valProp.getName(); }
453 
454     ALEMBIC_ABC_SAFE_CALL_END();
455 
456     return g_emptyStr;
457 }
458 
459 //-*****************************************************************************
460 template <class TRAITS>
getParent()461 Abc::ICompoundProperty ITypedGeomParam<TRAITS>::getParent() const
462 {
463     if ( m_isIndexed ) { return m_cprop.getParent(); }
464     else { return m_valProp.getParent(); }
465 }
466 
467 //-*****************************************************************************
468 template <class TRAITS>
getHeader()469 const AbcA::PropertyHeader &ITypedGeomParam<TRAITS>::getHeader() const
470 {
471     if ( m_isIndexed ) { return m_cprop.getHeader(); }
472     else { return m_valProp.getHeader(); }
473 }
474 
475 //-*****************************************************************************
476 template <class TRAITS>
getMetaData()477 const AbcA::MetaData &ITypedGeomParam<TRAITS>::getMetaData() const
478 {
479     if ( m_isIndexed ) { return m_cprop.getMetaData(); }
480     else { return m_valProp.getMetaData(); }
481 }
482 
483 //-*****************************************************************************
484 template <class TRAITS>
getTimeSampling()485 AbcA::TimeSamplingPtr ITypedGeomParam<TRAITS>::getTimeSampling() const
486 {
487     if ( m_valProp )
488     {
489         return m_valProp.getTimeSampling();
490     }
491     else if ( m_indicesProperty )
492     {
493         return m_indicesProperty.getTimeSampling();
494     }
495 
496     return AbcA::TimeSamplingPtr();
497 }
498 
499 //-*****************************************************************************
500 // TYPEDEFS
501 //-*****************************************************************************
502 
503 typedef ITypedGeomParam<BooleanTPTraits>         IBoolGeomParam;
504 typedef ITypedGeomParam<Uint8TPTraits>           IUcharGeomParam;
505 typedef ITypedGeomParam<Int8TPTraits>            ICharGeomParam;
506 typedef ITypedGeomParam<Uint16TPTraits>          IUInt16GeomParam;
507 typedef ITypedGeomParam<Int16TPTraits>           IInt16GeomParam;
508 typedef ITypedGeomParam<Uint32TPTraits>          IUInt32GeomParam;
509 typedef ITypedGeomParam<Int32TPTraits>           IInt32GeomParam;
510 typedef ITypedGeomParam<Uint64TPTraits>          IUInt64GeomParam;
511 typedef ITypedGeomParam<Int64TPTraits>           IInt64GeomParam;
512 typedef ITypedGeomParam<Float16TPTraits>         IHalfGeomParam;
513 typedef ITypedGeomParam<Float32TPTraits>         IFloatGeomParam;
514 typedef ITypedGeomParam<Float64TPTraits>         IDoubleGeomParam;
515 typedef ITypedGeomParam<StringTPTraits>          IStringGeomParam;
516 typedef ITypedGeomParam<WstringTPTraits>         IWstringGeomParam;
517 
518 typedef ITypedGeomParam<V2sTPTraits>             IV2sGeomParam;
519 typedef ITypedGeomParam<V2iTPTraits>             IV2iGeomParam;
520 typedef ITypedGeomParam<V2fTPTraits>             IV2fGeomParam;
521 typedef ITypedGeomParam<V2dTPTraits>             IV2dGeomParam;
522 
523 typedef ITypedGeomParam<V3sTPTraits>             IV3sGeomParam;
524 typedef ITypedGeomParam<V3iTPTraits>             IV3iGeomParam;
525 typedef ITypedGeomParam<V3fTPTraits>             IV3fGeomParam;
526 typedef ITypedGeomParam<V3dTPTraits>             IV3dGeomParam;
527 
528 typedef ITypedGeomParam<P2sTPTraits>             IP2sGeomParam;
529 typedef ITypedGeomParam<P2iTPTraits>             IP2iGeomParam;
530 typedef ITypedGeomParam<P2fTPTraits>             IP2fGeomParam;
531 typedef ITypedGeomParam<P2dTPTraits>             IP2dGeomParam;
532 
533 typedef ITypedGeomParam<P3sTPTraits>             IP3sGeomParam;
534 typedef ITypedGeomParam<P3iTPTraits>             IP3iGeomParam;
535 typedef ITypedGeomParam<P3fTPTraits>             IP3fGeomParam;
536 typedef ITypedGeomParam<P3dTPTraits>             IP3dGeomParam;
537 
538 typedef ITypedGeomParam<Box2sTPTraits>           IBox2sGeomParam;
539 typedef ITypedGeomParam<Box2iTPTraits>           IBox2iGeomParam;
540 typedef ITypedGeomParam<Box2fTPTraits>           IBox2fGeomParam;
541 typedef ITypedGeomParam<Box2dTPTraits>           IBox2dGeomParam;
542 
543 typedef ITypedGeomParam<Box3sTPTraits>           IBox3sGeomParam;
544 typedef ITypedGeomParam<Box3iTPTraits>           IBox3iGeomParam;
545 typedef ITypedGeomParam<Box3fTPTraits>           IBox3fGeomParam;
546 typedef ITypedGeomParam<Box3dTPTraits>           IBox3dGeomParam;
547 
548 typedef ITypedGeomParam<M33fTPTraits>            IM33fGeomParam;
549 typedef ITypedGeomParam<M33dTPTraits>            IM33dGeomParam;
550 typedef ITypedGeomParam<M44fTPTraits>            IM44fGeomParam;
551 typedef ITypedGeomParam<M44dTPTraits>            IM44dGeomParam;
552 
553 typedef ITypedGeomParam<QuatfTPTraits>           IQuatfGeomParam;
554 typedef ITypedGeomParam<QuatdTPTraits>           IQuatdGeomParam;
555 
556 typedef ITypedGeomParam<C3hTPTraits>             IC3hGeomParam;
557 typedef ITypedGeomParam<C3fTPTraits>             IC3fGeomParam;
558 typedef ITypedGeomParam<C3cTPTraits>             IC3cGeomParam;
559 
560 typedef ITypedGeomParam<C4hTPTraits>             IC4hGeomParam;
561 typedef ITypedGeomParam<C4fTPTraits>             IC4fGeomParam;
562 typedef ITypedGeomParam<C4cTPTraits>             IC4cGeomParam;
563 
564 typedef ITypedGeomParam<N2fTPTraits>             IN2fGeomParam;
565 typedef ITypedGeomParam<N2dTPTraits>             IN2dGeomParam;
566 
567 typedef ITypedGeomParam<N3fTPTraits>             IN3fGeomParam;
568 typedef ITypedGeomParam<N3dTPTraits>             IN3dGeomParam;
569 
570 } // End namespace ALEMBIC_VERSION_NS
571 
572 using namespace ALEMBIC_VERSION_NS;
573 
574 } // End namespace AbcGeom
575 } // End namespace Alembic
576 
577 #endif
578