1 //-*****************************************************************************
2 //
3 // Copyright (c) 2009-2011,
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_IGeometrySchema_h
38 #define Alembic_AbcGeom_IGeometrySchema_h
39 
40 #include <Alembic/Abc/ISchema.h>
41 #include <Alembic/AbcGeom/Foundation.h>
42 #include <Alembic/AbcGeom/IGeomParam.h>
43 #include <Alembic/AbcGeom/SchemaInfoDeclarations.h>
44 
45 namespace Alembic {
46 namespace AbcGeom {
47 namespace ALEMBIC_VERSION_NS {
48 
49 
50 //! This class holds properties common to all geometric classes that have a
51 //! physical volume.
52 //! - selfBounds
53 //! - childBounds (optional)
54 //! - GeomParams (optional)
55 //! - UserProperties (optional)
56 //!
57 //! This class is used to encapsulate common functionality of the
58 //! real Geometry schema classes, like IPoints and IPolyMesh and so on
59 template <class INFO>
60 class IGeomBaseSchema : public Abc::ISchema<INFO>
61 {
62 public:
63     //-*************************************************************************
64     // TYPEDEFS AND IDENTIFIERS
65     //-*************************************************************************
66 
67     typedef INFO info_type;
68 
69 
70     //-*************************************************************************
71     // Constructors that pass through to ISchema
72     //-*************************************************************************
73     //
74     //! The default constructor creates an empty ISchema.
75     //! Used to create "NULL/invalid" instances.
IGeomBaseSchema()76     IGeomBaseSchema() {}
77 
78     //! Delegates to Abc/ISchema, and then creates
79     //! properties that are present.
80     IGeomBaseSchema( const ICompoundProperty & iParent,
81                      const std::string &iName,
82                      const Argument &iArg0 = Argument(),
83                      const Argument &iArg1 = Argument() )
84     : Abc::ISchema<info_type>( iParent, iName, iArg0, iArg1 )
85     {
86         init( iArg0, iArg1 );
87     }
88 
89     //! Wrap an existing schema object
90     IGeomBaseSchema( const ICompoundProperty & iProp,
91                      const Abc::Argument &iArg0 = Abc::Argument(),
92                      const Abc::Argument &iArg1 = Abc::Argument() )
93       : Abc::ISchema<info_type>( iProp, iArg0, iArg1 )
94     {
95         init( iArg0, iArg1 );
96     }
97 
98     // Deprecated in favor of the constructor above
99     IGeomBaseSchema( const ICompoundProperty & iProp,
100                      Abc::WrapExistingFlag iFlag,
101                      const Abc::Argument &iArg0 = Abc::Argument(),
102                      const Abc::Argument &iArg1 = Abc::Argument() )
103       : Abc::ISchema<info_type>( iProp, iArg0, iArg1 )
104     {
105         init( iArg0, iArg1 );
106     }
107 
108     //! Copy constructor
IGeomBaseSchema(const IGeomBaseSchema & iCopy)109     IGeomBaseSchema( const IGeomBaseSchema& iCopy )
110       : Abc::ISchema<info_type>()
111     {
112         *this = iCopy;
113     }
114 
init(const Abc::Argument & iArg0,const Abc::Argument & iArg1)115     void init( const Abc::Argument &iArg0, const Abc::Argument &iArg1 )
116     {
117         ALEMBIC_ABC_SAFE_CALL_BEGIN( "IGeomBaseSchema::init()" );
118 
119         Abc::Arguments args;
120         iArg0.setInto( args );
121         iArg1.setInto( args );
122 
123         AbcA::CompoundPropertyReaderPtr _this = this->getPtr();
124 
125         m_selfBoundsProperty = Abc::IBox3dProperty( _this, ".selfBnds",
126             iArg0, iArg1 );
127         if ( this->getPropertyHeader( ".childBnds" ) != NULL )
128         {
129             m_childBoundsProperty = Abc::IBox3dProperty( _this,
130                 ".childBnds", iArg0, iArg1 );
131         }
132 
133         if ( this->getPropertyHeader( ".arbGeomParams" ) != NULL )
134         {
135             m_arbGeomParams = Abc::ICompoundProperty( _this, ".arbGeomParams",
136                 args.getErrorHandlerPolicy() );
137         }
138         if ( this->getPropertyHeader( ".userProperties" ) != NULL )
139         {
140             m_userProperties = Abc::ICompoundProperty( _this, ".userProperties",
141                 args.getErrorHandlerPolicy() );
142         }
143 
144         ALEMBIC_ABC_SAFE_CALL_END();
145     }
146 
reset()147     virtual void reset ()
148     {
149         m_selfBoundsProperty.reset();
150         m_childBoundsProperty.reset();
151         m_arbGeomParams.reset();
152         m_userProperties.reset();
153         Abc::ISchema<info_type>::reset();
154     }
155 
valid()156     virtual bool valid() const
157     {
158         // Only selfBounds is required, all others are optional
159         return ( Abc::ISchema<info_type>::valid() &&
160                 m_selfBoundsProperty.valid() );
161     }
162 
getSelfBoundsProperty()163     Abc::IBox3dProperty getSelfBoundsProperty() const
164     {
165         return m_selfBoundsProperty;
166     }
167 
getChildBoundsProperty()168     Abc::IBox3dProperty getChildBoundsProperty() const
169     {
170         return m_childBoundsProperty;
171     }
172 
173     // compound property to use as parent for any arbitrary GeomParams
174     // underneath it
getArbGeomParams()175     ICompoundProperty getArbGeomParams() const { return m_arbGeomParams; }
176 
177     // compound property to use as parent for any user workflow specific
178     // properties
getUserProperties()179     ICompoundProperty getUserProperties() const { return m_userProperties; }
180 
181 protected:
182     // Only selfBounds is required, all others are optional
183     Abc::IBox3dProperty m_selfBoundsProperty;
184     Abc::IBox3dProperty m_childBoundsProperty;
185 
186     Abc::ICompoundProperty m_arbGeomParams;
187     Abc::ICompoundProperty m_userProperties;
188 
189 };
190 
191 //-*****************************************************************************
192 //! IGeomBase - A generic base set of properties and methods that encapsulate
193 //! things common to AbcGeom types that have a physical volume.
194 //! - self bounds
195 //! - children bounds (optional)
196 //! - argbGeomParams (optional)
197 //! - userProperties (optional)
198 //! This class is a concrete instantiation of IGeomBaseSchema.
199 //! Your archive might contain PolyMesh and SubD and Curves
200 //! and Points objects etc. This class, IGeomBase, gives you
201 //! access to the generic parts of those objects. For example, if you
202 //! just wish to iterate through an archive's hierarchy to examine bounding
203 //! regions this class could be helpful to you. Then when you actually
204 //! need to access the real data in the geometric type you can
205 //! always create the needed type of I<geom type> object> via kWrapExisting.
206 class IGeomBase : public IGeomBaseSchema<GeomBaseSchemaInfo>
207 {
208 public:
209     typedef IGeomBase this_type;
210 
211     class Sample
212     {
213     public:
214         typedef Sample this_type;
215 
216         // Users don't ever create this data directly.
Sample()217         Sample() { reset(); }
218 
getSelfBounds()219         Abc::Box3d getSelfBounds() const { return m_selfBounds; }
220 
reset()221         void reset()
222         {
223             m_selfBounds.makeEmpty();
224         }
225 
226     protected:
227         friend class IGeomBase;
228         Abc::Box3d m_selfBounds;
229     };
230 
231 public:
232     //! By convention we always define this_type in AbcGeom classes.
233     //! Used by unspecified-bool-type conversion below
234 
235     //-*************************************************************************
236     // CONSTRUCTION, DESTRUCTION, ASSIGNMENT
237     //-*************************************************************************
238 
239     //! The default constructor creates an empty GeomBase
IGeomBase()240     IGeomBase() {}
241 
242     IGeomBase( const ICompoundProperty &iParent,
243                const std::string &iName,
244                const Abc::Argument &iArg0 = Abc::Argument(),
245                const Abc::Argument &iArg1 = Abc::Argument() )
246 
247         // We don't want strict matching of the title because the real schema
248         // is going to be something like "AbcGeom_<type>_vX"
249       : IGeomBaseSchema<GeomBaseSchemaInfo>( iParent, iName, kNoMatching )
250     {
251         init( iArg0, iArg1 );
252     }
253 
254     IGeomBase( const ICompoundProperty & iThis,
255                const Abc::Argument &iArg0 = Abc::Argument(),
256                const Abc::Argument &iArg1 = Abc::Argument() )
257         // We don't want strict matching of the title because the real schema
258         // is going to be something like "AbcGeom_<type>_vX"
259     : IGeomBaseSchema<GeomBaseSchemaInfo>( iThis, kNoMatching )
260     {
261         init( iArg0, iArg1 );
262     }
263 
264     IGeomBase( const ICompoundProperty & iThis,
265                Abc::WrapExistingFlag iFlag,
266                const Abc::Argument &iArg0 = Abc::Argument(),
267                const Abc::Argument &iArg1 = Abc::Argument() )
268     : IGeomBaseSchema<GeomBaseSchemaInfo>( iThis, kNoMatching )
269     {
270         init( iArg0, iArg1 );
271     }
272 
273     //! Copy constructor.
IGeomBase(const IGeomBase & iCopy)274     IGeomBase(const IGeomBase & iCopy)
275         : IGeomBaseSchema<GeomBaseSchemaInfo>()
276     {
277         *this = iCopy;
278     }
279 
280     //! Default assignment operator used.
281 
282     //-*************************************************************************
283     // SCALAR PROPERTY READER FUNCTIONALITY
284     //-*************************************************************************
285 
286     //! Return the number of samples contained in the property.
287     //! This can be any number, including zero.
288     //! This returns the number of samples that were written, independently
289     //! of whether or not they were constant.
getNumSamples()290     size_t getNumSamples() const
291     { return m_selfBoundsProperty.getNumSamples(); }
292 
293     //! Ask if we're constant - no change in value amongst samples,
294     //! regardless of the time sampling.
isConstant()295     bool isConstant() const
296     { return m_selfBoundsProperty.isConstant(); }
297 
298     //! Time sampling Information.
299     //!
getTimeSampling()300     AbcA::TimeSamplingPtr getTimeSampling() const
301     {
302         if ( m_selfBoundsProperty.valid() )
303         {
304             return m_selfBoundsProperty.getTimeSampling();
305         }
306         else
307         {
308             return getObject().getArchive().getTimeSampling( 0 );
309         }
310     }
311 
312     //-*************************************************************************
313     void get( Sample &oSample,
314               const Abc::ISampleSelector &iSS = Abc::ISampleSelector() ) const
315     {
316         ALEMBIC_ABC_SAFE_CALL_BEGIN( "IGeomBase::get()" );
317 
318         m_selfBoundsProperty.get( oSample.m_selfBounds, iSS );
319 
320         ALEMBIC_ABC_SAFE_CALL_END();
321     }
322 
323     //-*************************************************************************
324     Sample getValue( const Abc::ISampleSelector &iSS = Abc::ISampleSelector() ) const
325     {
326         Sample smp;
327         get( smp, iSS );
328         return smp;
329     }
330 
331     //-*************************************************************************
getArbGeomParams()332     Abc::ICompoundProperty getArbGeomParams() const { return m_arbGeomParams; }
333 
334     //-*************************************************************************
getUserProperties()335     Abc::ICompoundProperty getUserProperties() const { return m_userProperties; }
336 
337     //-*************************************************************************
338     //! Reset returns this function set to an empty, default
339     //! state.
reset()340     void reset()
341     {
342         IGeomBaseSchema<GeomBaseSchemaInfo>::reset();
343     }
344 
345     //-*************************************************************************
346     //! Valid returns whether this function set is
347     //! valid.
valid()348     bool valid() const
349     {
350         return ( IGeomBaseSchema<GeomBaseSchemaInfo>::valid() );
351     }
352 
353     //-*************************************************************************
354     //! unspecified-bool-type operator overload.
355     //! ...
356     ALEMBIC_OVERRIDE_OPERATOR_BOOL( IGeomBase::valid() );
357 
358     //-*************************************************************************
359     //! This will check whether or not a given entity (as represented by
360     //! metadata) strictly matches the interpretation of this
361     //! schema object.
362     static bool matches( const AbcA::MetaData &iMetaData,
363                          SchemaInterpMatching iMatching = kStrictMatching )
364     {
365         if ( iMatching == kNoMatching )
366         { return true; }
367 
368         if ( iMatching == kStrictMatching || iMatching == kSchemaTitleMatching )
369         {
370             return iMetaData.get( "schemaBaseType" ) ==
371                 GeomBaseSchemaInfo::title();
372         }
373 
374         return false;
375     }
376 
377     //-*************************************************************************
378     //! This will check whether or not a given object (as represented by
379     //! an object header) strictly matches the interpretation of this
380     //! schema object, as well as the data type.
381     static bool matches( const AbcA::PropertyHeader &iHeader,
382                          SchemaInterpMatching iMatching = kStrictMatching )
383     {
384         return matches( iHeader.getMetaData(), iMatching );
385     }
386 
387 };
388 
389 //-*****************************************************************************
390 typedef Abc::ISchemaObject<IGeomBase> IGeomBaseObject;
391 
392 } // End namespace ALEMBIC_VERSION_NS
393 
394 using namespace ALEMBIC_VERSION_NS;
395 
396 } // End namespace AbcGeom
397 } // End namespace Alembic
398 
399 #endif
400