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 #include <Alembic/AbcGeom/All.h>
38 #include <Alembic/AbcCoreFactory/All.h>
39 
40 #include <ImathBoxAlgo.h>
41 
42 #include <iostream>
43 
44 //-*****************************************************************************
45 using namespace ::Alembic::AbcGeom;
46 
47 static Box3d g_bounds;
48 
49 //-*****************************************************************************
accumXform(M44d & xf,IObject obj,chrono_t seconds)50 void accumXform( M44d &xf, IObject obj, chrono_t seconds )
51 {
52     if ( IXform::matches( obj.getHeader() ) )
53     {
54         IXform x( obj, kWrapExisting );
55         XformSample xs;
56         ISampleSelector sel( seconds );
57         x.getSchema().get( xs, sel );
58         xf *= xs.getMatrix();
59     }
60 }
61 
62 //-*****************************************************************************
getFinalMatrix(IObject & iObj,chrono_t seconds)63 M44d getFinalMatrix( IObject &iObj, chrono_t seconds )
64 {
65     M44d xf;
66     xf.makeIdentity();
67 
68     IObject parent = iObj.getParent();
69 
70     while ( parent )
71     {
72         accumXform( xf, parent, seconds );
73         parent = parent.getParent();
74     }
75 
76     return xf;
77 }
78 
79 //-*****************************************************************************
getBounds(IObject iObj,chrono_t seconds)80 Box3d getBounds( IObject iObj, chrono_t seconds )
81 {
82     Box3d bnds;
83     bnds.makeEmpty();
84 
85     M44d xf = getFinalMatrix( iObj, seconds );
86     IBox3dProperty boxProp;
87 
88     if ( ICurves::matches( iObj.getMetaData() ) )
89     {
90         ICurves curves( iObj, kWrapExisting );
91         ICurvesSchema cs = curves.getSchema();
92         boxProp = cs.getSelfBoundsProperty();
93     }
94     else if ( INuPatch::matches( iObj.getMetaData() ) )
95     {
96         INuPatch patch( iObj, kWrapExisting );
97         INuPatchSchema ps = patch.getSchema();
98         boxProp = ps.getSelfBoundsProperty();
99     }
100     else if ( IPolyMesh::matches( iObj.getMetaData() ) )
101     {
102         IPolyMesh mesh( iObj, kWrapExisting );
103         IPolyMeshSchema ms = mesh.getSchema();
104         boxProp = ms.getSelfBoundsProperty();
105     }
106     else if ( IPoints::matches( iObj.getMetaData() ) )
107     {
108         IPoints pts( iObj, kWrapExisting );
109         IPointsSchema ps = pts.getSchema();
110         boxProp = ps.getSelfBoundsProperty();
111     }
112     else if ( ISubD::matches( iObj.getMetaData() ) )
113     {
114         ISubD mesh( iObj, kWrapExisting );
115         ISubDSchema ms = mesh.getSchema();
116         boxProp = ms.getSelfBoundsProperty();
117     }
118 
119     if ( boxProp.valid() )
120     {
121         ISampleSelector sel( seconds );
122         bnds = boxProp.getValue( sel );
123         bnds = Imath::transform( bnds, xf );
124         g_bounds.extendBy( bnds );
125     }
126 
127     g_bounds.extendBy( bnds );
128 
129     return bnds;
130 }
131 
132 //-*****************************************************************************
visitObject(IObject iObj,chrono_t seconds)133 void visitObject( IObject iObj, chrono_t seconds )
134 {
135     std::string path = iObj.getFullName();
136 
137     const MetaData &md = iObj.getMetaData();
138 
139     if ( ICurves::matches( md ) ||
140         INuPatch::matches( md ) ||
141         IPoints::matches( md ) ||
142         IPolyMesh::matches( md ) ||
143         ISubDSchema::matches( md ) )
144     {
145         Box3d bnds = getBounds( iObj, seconds );
146         std::cout << path << " " << bnds.min << " " << bnds.max << std::endl;
147     }
148 
149     // now the child objects
150     for ( size_t i = 0 ; i < iObj.getNumChildren() ; i++ )
151     {
152         visitObject( IObject( iObj, iObj.getChildHeader( i ).getName() ),
153                      seconds );
154     }
155 }
156 
157 //-*****************************************************************************
158 //-*****************************************************************************
159 // DO IT.
160 //-*****************************************************************************
161 //-*****************************************************************************
main(int argc,char * argv[])162 int main( int argc, char *argv[] )
163 {
164     if ( argc != 2 && argc != 3 )
165     {
166         std::cerr << "USAGE: " << argv[0] << " <AlembicArchive.abc> <seconds>"
167                   << std::endl;
168         exit( -1 );
169     }
170 
171     chrono_t seconds = 0.0;
172     if ( argc == 3 )
173     {
174         seconds = atof(argv[2]);
175     }
176 
177     // Scoped.
178     g_bounds.makeEmpty();
179     {
180         Alembic::AbcCoreFactory::IFactory factory;
181         factory.setPolicy(ErrorHandler::kQuietNoopPolicy);
182         IArchive archive = factory.getArchive( argv[1] );
183         visitObject( archive.getTop(), seconds );
184     }
185 
186     std::cout << "/" << " " << g_bounds.min << " " << g_bounds.max << std::endl;
187 
188     return 0;
189 }
190