1 //-*****************************************************************************
2 //
3 // Copyright (c) 2009-2012,
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 #include <Alembic/Abc/All.h>
38 #include <Alembic/AbcCoreFactory/All.h>
39 #include <Alembic/AbcCoreOgawa/All.h>
40 #include <Alembic/AbcCoreAbstract/Tests/Assert.h>
41 
42 #ifdef ALEMBIC_WITH_HDF5
43 #include <Alembic/AbcCoreHDF5/All.h>
44 #endif
45 
46 #include <ImathMath.h>
47 
48 #include <limits>
49 
50 namespace Abc = Alembic::Abc;
51 using namespace Abc;
52 
53 namespace AbcF = Alembic::AbcCoreFactory;
54 
55 using Alembic::AbcCoreAbstract::chrono_t;
56 using Alembic::AbcCoreAbstract::index_t;
57 using Alembic::Util::uint32_t;
58 using Alembic::Util::float32_t;
59 
60 static const V3f scalarV3fval( -1.0f, 32.0f, -90.0f );
61 
62 static const chrono_t startTime = 5.7;
63 
64 static const chrono_t dt = 1.0 / 24.0;
65 
66 static const chrono_t CHRONO_EPSILON = \
67     std::numeric_limits<chrono_t>::epsilon() * 32.0;
68 
69 //-*****************************************************************************
simpleTestOut(const std::string & iArchiveName,bool useOgawa)70 void simpleTestOut( const std::string &iArchiveName, bool useOgawa )
71 {
72 
73     OArchive archive;
74     if (useOgawa)
75     {
76         archive = OArchive( Alembic::AbcCoreOgawa::WriteArchive(),
77             iArchiveName, ErrorHandler::kThrowPolicy );
78     }
79 #ifdef ALEMBIC_WITH_HDF5
80     else
81     {
82         archive = OArchive( Alembic::AbcCoreHDF5::WriteArchive(),
83             iArchiveName, ErrorHandler::kThrowPolicy );
84     }
85 #endif
86 
87     // all child Objects in an Archive are actually children of the single
88     // top Object in an Archive
89     OObject topobj = archive.getTop();
90 
91     // 0th archive child
92     OObject ac0( topobj, "ac0" );
93     // 0th archive child child
94     OObject acc0( ac0, "acc0" );
95 
96     // all property manipulation is through an Object's single CompoundProperty
97     OCompoundProperty ac0Props = ac0.getProperties();
98     OCompoundProperty acc0Props = acc0.getProperties();
99 
100     // some scalar props
101     OV3fProperty ac0V3fp0( ac0Props, "ac0V3fp0" );
102     ac0V3fp0.set( scalarV3fval );
103 
104     TimeSampling ts(dt, startTime);
105     Alembic::Util::uint32_t tsidx = archive.addTimeSampling(ts);
106 
107     // now some array props
108     OV3fArrayProperty acc0V3fap0( acc0Props, "acc0V3fap0", tsidx );
109 
110     chrono_t t = startTime;
111     const size_t numPoints = 7;
112     const size_t numSamps = 5;
113 
114     std::vector<V3f> points( numPoints );
115 
116     for ( size_t i = 0 ; i < numSamps ; ++i )
117     {
118         for ( std::vector<V3f>::iterator iter = points.begin() ;
119               iter != points.end() ; ++iter )
120         {
121             (*iter) = V3f( i + t, i + t, i + t );
122         }
123 
124         acc0V3fap0.set( points );
125         t += dt;
126     }
127 
128     // OK, test some parentage
129     {
130         OObject _foo;
131         OObject _parent = acc0;
132         while ( _parent )
133         {
134             std::cout << "_parent.getFullName(): " << _parent.getFullName()
135                       << std::endl;
136             _foo = _parent.getParent();
137             _parent = _foo;
138         }
139     }
140 
141     {
142         OCompoundProperty _foo;
143         OCompoundProperty _parent = acc0Props;
144         while ( _parent )
145         {
146             std::cout << "_parent.getName(): " << _parent.getName()
147                       << std::endl;
148             _foo = _parent.getParent();
149             _parent = _foo;
150         }
151     }
152 
153     // if the program exits, it means parenting works.
154 }
155 
156 //-*****************************************************************************
simpleTestIn(const std::string & iArchiveName)157 void simpleTestIn( const std::string &iArchiveName )
158 {
159     AbcF::IFactory factory;
160     factory.setPolicy(  ErrorHandler::kThrowPolicy );
161     AbcF::IFactory::CoreType coreType;
162     IArchive archive = factory.getArchive(iArchiveName, coreType);
163 
164     // an archive has a single top object which contains all its children
165     IObject topObject = archive.getTop();
166 
167     IObject ac0( topObject, "ac0" );
168     IObject acc0( ac0, "acc0" );
169 
170     // an object contains a single compound property that contains all
171     // sub-properties; all property access is through that.
172     ICompoundProperty ac0Props = ac0.getProperties();
173     ICompoundProperty acc0Props = acc0.getProperties();
174 
175     IV3fProperty ac0V3fp0( ac0Props, "ac0V3fp0" );
176 
177     IV3fArrayProperty acc0V3fap0( acc0Props, "acc0V3fap0" );
178     V3fArraySamplePtr acc0V3fap0SampPtr;
179 
180     const size_t numSamps = acc0V3fap0.getNumSamples();
181 
182     std::cout << "acc0V3fap0 has " << numSamps << " samples." << std::endl;
183 
184     for ( size_t i = 0 ; i < numSamps ; ++i )
185     {
186         acc0V3fap0.get( acc0V3fap0SampPtr, i );
187         size_t numPoints = acc0V3fap0SampPtr->size();
188 
189         chrono_t time = acc0V3fap0.getTimeSampling()->getSampleTime( i );
190 
191         chrono_t compTime = startTime + ( i * dt );
192 
193         std::cout << "acc0fap0 at sample " << i << " is at time "
194                   << time
195                   << " and has " << numPoints << " points "
196                   << " with the values:" << std::endl;
197 
198         float32_t elementVal = i + time;
199 
200         TESTING_ASSERT( (*acc0V3fap0SampPtr)[0][0] == elementVal );
201 
202         TESTING_ASSERT( Imath::equalWithAbsError( time, compTime,
203                                                   CHRONO_EPSILON ) );
204 
205 
206         for ( size_t j = 0 ; j < numPoints ; ++j )
207         {
208             std::cout << (*acc0V3fap0SampPtr)[j] << ", ";
209         }
210         std::cout << std::endl << std::endl;
211     }
212 
213     // OK, test some parentage
214     {
215         IObject _foo;
216         IObject _parent = acc0;
217         while ( _parent )
218         {
219             std::cout << "_parent.getFullName(): " << _parent.getFullName()
220                       << std::endl;
221             _foo = _parent.getParent();
222             _parent = _foo;
223         }
224     }
225 
226     {
227         ICompoundProperty _foo;
228         ICompoundProperty _parent = acc0Props;
229         while ( _parent )
230         {
231             std::cout << "_parent.getName(): " << _parent.getName()
232                       << std::endl;
233             _foo = _parent.getParent();
234             _parent = _foo;
235         }
236     }
237 
238     // if the program exits, it means parenting works
239 }
240 
scopingTest(bool useOgawa)241 void scopingTest(bool useOgawa)
242 {
243     {
244         ODoubleProperty propScalar;
245         ODoubleArrayProperty propArray;
246         {
247 
248             OArchive archive;
249             if (useOgawa)
250             {
251                 archive = CreateArchiveWithInfo(
252                     Alembic::AbcCoreOgawa::WriteArchive(), "propScopeTest.abc",
253                     "Alembic test", "", MetaData() );
254             }
255 #ifdef ALEMBIC_WITH_HDF5
256             else
257             {
258                 archive = CreateArchiveWithInfo(
259                     Alembic::AbcCoreHDF5::WriteArchive(), "propScopeTest.abc",
260                     "Alembic test", "", MetaData() );
261             }
262 #endif
263 
264             OObject childA( archive.getTop(), "a" );
265 
266             propScalar = ODoubleProperty(childA.getProperties(), "scalar", 0);
267 
268             propArray = ODoubleArrayProperty(childA.getProperties(),
269                 "array", 0);
270         }
271 
272         std::vector< double > values(3, 2.0);
273         propArray.set( values );
274         propScalar.set( 4.0 );
275         propScalar.set( 5.0 );
276         TESTING_ASSERT(
277             propArray.getParent().getObject().getArchive().getName() ==
278             "propScopeTest.abc");
279         TESTING_ASSERT(
280             propScalar.getParent().getObject().getArchive().getName() ==
281             "propScopeTest.abc");
282     }
283 
284     {
285         IDoubleProperty propScalar;
286         IDoubleArrayProperty propArray;
287         {
288             AbcF::IFactory factory;
289             AbcF::IFactory::CoreType coreType;
290             IArchive archive = factory.getArchive("propScopeTest.abc",
291                                                   coreType);
292             IObject top(archive.getTop(), "a");
293             propScalar = IDoubleProperty(top.getProperties(), "scalar");
294             propArray = IDoubleArrayProperty(top.getProperties(), "array");
295         }
296         TESTING_ASSERT(
297             propArray.getParent().getObject().getArchive().getName() ==
298             "propScopeTest.abc");
299         TESTING_ASSERT(
300             propScalar.getParent().getObject().getArchive().getName() ==
301             "propScopeTest.abc");
302 
303         DoubleArraySamplePtr samp;
304         size_t sampNum = 0;
305         propArray.get(samp, sampNum);
306         TESTING_ASSERT( samp->size() == 3 );
307         TESTING_ASSERT( (*samp)[0] == 2.0 && (*samp)[1] == 2.0 &&
308                         (*samp)[2] == 2.0 );
309 
310         double scalarVal = 0.0;
311         propScalar.get( scalarVal, sampNum );
312         TESTING_ASSERT( scalarVal == 4.0 );
313         sampNum ++;
314         propScalar.get( scalarVal, sampNum );
315         TESTING_ASSERT( scalarVal == 5.0 );
316     }
317 }
318 
319 //-*****************************************************************************
main(int argc,char * argv[])320 int main( int argc, char *argv[] )
321 {
322     const std::string arkive( "parentstest.abc" );
323 
324     bool useOgawa = true;
325     simpleTestOut( arkive, useOgawa );
326     simpleTestIn( arkive );
327     scopingTest(useOgawa);
328 #ifdef ALEMBIC_WITH_HDF5
329     useOgawa = false;
330     simpleTestOut( arkive, useOgawa );
331     simpleTestIn( arkive );
332     scopingTest(useOgawa);
333 #endif
334     return 0;
335 }
336