/src/alembic/lib/Alembic/AbcGeom/ISubD.cpp
Line | Count | Source (jump to first uncovered line) |
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/AbcGeom/ISubD.h> |
38 | | |
39 | | namespace Alembic { |
40 | | namespace AbcGeom { |
41 | | namespace ALEMBIC_VERSION_NS { |
42 | | |
43 | | //-***************************************************************************** |
44 | | MeshTopologyVariance ISubDSchema::getTopologyVariance() const |
45 | 0 | { |
46 | 0 | ALEMBIC_ABC_SAFE_CALL_BEGIN( "ISubDSchema::getTopologyVariance()" ); |
47 | |
|
48 | 0 | if ( m_faceIndicesProperty.isConstant() && m_faceCountsProperty.isConstant() ) |
49 | 0 | { |
50 | 0 | if ( m_positionsProperty.isConstant() ) |
51 | 0 | { |
52 | 0 | return kConstantTopology; |
53 | 0 | } |
54 | 0 | else |
55 | 0 | { |
56 | 0 | return kHomogenousTopology; |
57 | 0 | } |
58 | 0 | } |
59 | 0 | else |
60 | 0 | { |
61 | 0 | return kHeterogenousTopology; |
62 | 0 | } |
63 | |
|
64 | 0 | ALEMBIC_ABC_SAFE_CALL_END(); |
65 | | |
66 | | // Not all error handlers throw |
67 | 0 | return kConstantTopology; |
68 | 0 | } |
69 | | |
70 | | //-***************************************************************************** |
71 | | size_t ISubDSchema::getNumSamples() const |
72 | 0 | { |
73 | 0 | size_t max = 0; |
74 | |
|
75 | 0 | for ( size_t i = 0 ; i < this->getNumProperties() ; i++ ) |
76 | 0 | { |
77 | 0 | const AbcA::PropertyHeader& ph = this->getPropertyHeader( i ); |
78 | 0 | if ( ph.isArray() ) |
79 | 0 | { |
80 | 0 | max = std::max( max, |
81 | 0 | Abc::IArrayProperty( |
82 | 0 | this->getPtr(), |
83 | 0 | ph.getName() ).getNumSamples() ); |
84 | 0 | } |
85 | 0 | else if ( ph.isScalar() ) |
86 | 0 | { |
87 | 0 | max = std::max( max, |
88 | 0 | Abc::IScalarProperty( |
89 | 0 | this->getPtr(), |
90 | 0 | ph.getName() ).getNumSamples() ); |
91 | 0 | } |
92 | 0 | } |
93 | |
|
94 | 0 | return max; |
95 | 0 | } |
96 | | |
97 | | //-***************************************************************************** |
98 | | void ISubDSchema::get( ISubDSchema::Sample &oSample, |
99 | | const Abc::ISampleSelector &iSS ) const |
100 | 0 | { |
101 | 0 | ALEMBIC_ABC_SAFE_CALL_BEGIN( "ISubDSchema::get()" ); |
102 | |
|
103 | 0 | m_positionsProperty.get( oSample.m_positions, iSS ); |
104 | 0 | m_faceIndicesProperty.get( oSample.m_faceIndices, iSS ); |
105 | 0 | m_faceCountsProperty.get( oSample.m_faceCounts, iSS ); |
106 | |
|
107 | 0 | if ( m_faceVaryingInterpolateBoundaryProperty ) |
108 | 0 | { |
109 | 0 | m_faceVaryingInterpolateBoundaryProperty.get( |
110 | 0 | oSample.m_faceVaryingInterpolateBoundary, iSS ); |
111 | 0 | } |
112 | 0 | else |
113 | 0 | { |
114 | 0 | oSample.m_faceVaryingInterpolateBoundary = 0; |
115 | 0 | } |
116 | |
|
117 | 0 | if ( m_faceVaryingPropagateCornersProperty ) |
118 | 0 | { |
119 | 0 | m_faceVaryingPropagateCornersProperty.get( |
120 | 0 | oSample.m_faceVaryingPropagateCorners, iSS ); |
121 | 0 | } |
122 | 0 | else |
123 | 0 | { |
124 | 0 | oSample.m_faceVaryingPropagateCorners = 0; |
125 | 0 | } |
126 | |
|
127 | 0 | if ( m_interpolateBoundaryProperty ) |
128 | 0 | { |
129 | 0 | m_interpolateBoundaryProperty.get( oSample.m_interpolateBoundary, iSS ); |
130 | 0 | } |
131 | 0 | else |
132 | 0 | { |
133 | 0 | oSample.m_interpolateBoundary = 0; |
134 | 0 | } |
135 | |
|
136 | 0 | m_selfBoundsProperty.get( oSample.m_selfBounds, iSS ); |
137 | |
|
138 | 0 | if ( m_creaseIndicesProperty ) |
139 | 0 | { m_creaseIndicesProperty.get( oSample.m_creaseIndices, iSS ); } |
140 | |
|
141 | 0 | if ( m_creaseLengthsProperty ) |
142 | 0 | { m_creaseLengthsProperty.get( oSample.m_creaseLengths, iSS ); } |
143 | |
|
144 | 0 | if ( m_creaseSharpnessesProperty ) |
145 | 0 | { m_creaseSharpnessesProperty.get( oSample.m_creaseSharpnesses, iSS ); } |
146 | |
|
147 | 0 | if ( m_cornerIndicesProperty ) |
148 | 0 | { m_cornerIndicesProperty.get( oSample.m_cornerIndices, iSS ); } |
149 | |
|
150 | 0 | if ( m_cornerSharpnessesProperty ) |
151 | 0 | { m_cornerSharpnessesProperty.get( oSample.m_cornerSharpnesses, iSS ); } |
152 | |
|
153 | 0 | if ( m_holesProperty ) |
154 | 0 | { m_holesProperty.get( oSample.m_holes, iSS ); } |
155 | |
|
156 | 0 | if ( m_subdSchemeProperty ) |
157 | 0 | { |
158 | 0 | m_subdSchemeProperty.get( oSample.m_subdScheme, iSS ); |
159 | 0 | } |
160 | 0 | else |
161 | 0 | { |
162 | 0 | oSample.m_subdScheme = "catmull-clark"; |
163 | 0 | } |
164 | |
|
165 | 0 | if ( m_velocitiesProperty && m_velocitiesProperty.getNumSamples() > 0 ) |
166 | 0 | { m_velocitiesProperty.get( oSample.m_velocities, iSS ); } |
167 | |
|
168 | 0 | ALEMBIC_ABC_SAFE_CALL_END(); |
169 | 0 | } |
170 | | |
171 | | //-***************************************************************************** |
172 | | const ISubDSchema & |
173 | | ISubDSchema::operator=(const ISubDSchema & rhs) |
174 | 0 | { |
175 | 0 | IGeomBaseSchema<SubDSchemaInfo>::operator=(rhs); |
176 | |
|
177 | 0 | m_positionsProperty = rhs.m_positionsProperty; |
178 | 0 | m_velocitiesProperty = rhs.m_velocitiesProperty; |
179 | 0 | m_faceIndicesProperty = rhs.m_faceIndicesProperty; |
180 | 0 | m_faceCountsProperty = rhs.m_faceCountsProperty; |
181 | 0 | m_faceVaryingInterpolateBoundaryProperty = |
182 | 0 | rhs.m_faceVaryingInterpolateBoundaryProperty; |
183 | 0 | m_faceVaryingPropagateCornersProperty = |
184 | 0 | rhs.m_faceVaryingPropagateCornersProperty; |
185 | 0 | m_interpolateBoundaryProperty = rhs.m_interpolateBoundaryProperty; |
186 | 0 | m_creaseIndicesProperty = rhs.m_creaseIndicesProperty; |
187 | 0 | m_creaseLengthsProperty = rhs.m_creaseLengthsProperty; |
188 | 0 | m_creaseSharpnessesProperty = rhs.m_creaseSharpnessesProperty; |
189 | 0 | m_cornerIndicesProperty = rhs.m_cornerIndicesProperty; |
190 | 0 | m_cornerSharpnessesProperty = rhs.m_cornerSharpnessesProperty; |
191 | 0 | m_holesProperty = rhs.m_holesProperty; |
192 | 0 | m_subdSchemeProperty = rhs.m_subdSchemeProperty; |
193 | 0 | m_uvsParam = rhs.m_uvsParam; |
194 | 0 | m_faceVaryingInterpolateBoundaryProperty = |
195 | 0 | rhs.m_faceVaryingInterpolateBoundaryProperty; |
196 | | |
197 | | // lock, reset |
198 | 0 | Alembic::Util::scoped_lock l(m_faceSetsMutex); |
199 | 0 | m_faceSetsLoaded = false; |
200 | 0 | m_faceSets.clear(); |
201 | 0 | return *this; |
202 | 0 | } |
203 | | |
204 | | //-***************************************************************************** |
205 | | void ISubDSchema::init( const Abc::Argument &iArg0, |
206 | | const Abc::Argument &iArg1 ) |
207 | 0 | { |
208 | 0 | ALEMBIC_ABC_SAFE_CALL_BEGIN( "ISubDSchema::init()" ); |
209 | |
|
210 | 0 | AbcA::CompoundPropertyReaderPtr _this = this->getPtr(); |
211 | |
|
212 | 0 | Abc::Arguments args; |
213 | 0 | iArg0.setInto( args ); |
214 | 0 | iArg1.setInto( args ); |
215 | | |
216 | | // no matching so we pick up old assets written as V3f |
217 | 0 | m_positionsProperty = Abc::IP3fArrayProperty( _this, "P", kNoMatching, |
218 | 0 | args.getErrorHandlerPolicy() ); |
219 | |
|
220 | 0 | m_faceIndicesProperty = Abc::IInt32ArrayProperty( _this, ".faceIndices", |
221 | 0 | iArg0, iArg1 ); |
222 | 0 | m_faceCountsProperty = Abc::IInt32ArrayProperty( _this, ".faceCounts", |
223 | 0 | iArg0, iArg1 ); |
224 | |
|
225 | 0 | if ( this->getPropertyHeader(".faceVaryingInterpolateBoundary") != NULL ) |
226 | 0 | { |
227 | 0 | m_faceVaryingInterpolateBoundaryProperty = |
228 | 0 | Abc::IInt32Property( _this, ".faceVaryingInterpolateBoundary", |
229 | 0 | iArg0, iArg1 ); |
230 | 0 | } |
231 | |
|
232 | 0 | if ( this->getPropertyHeader(".faceVaryingPropagateCorners") != NULL ) |
233 | 0 | { |
234 | 0 | m_faceVaryingPropagateCornersProperty = |
235 | 0 | Abc::IInt32Property( _this, ".faceVaryingPropagateCorners", |
236 | 0 | iArg0, iArg1 ); |
237 | 0 | } |
238 | |
|
239 | 0 | if ( this->getPropertyHeader(".interpolateBoundary") != NULL ) |
240 | 0 | { |
241 | 0 | m_interpolateBoundaryProperty = |
242 | 0 | Abc::IInt32Property( _this, ".interpolateBoundary", iArg0, iArg1 ); |
243 | 0 | } |
244 | | |
245 | | // creases, corners, and holes optionally exist |
246 | 0 | if ( this->getPropertyHeader(".creaseIndices") != NULL) |
247 | 0 | { |
248 | 0 | m_creaseIndicesProperty = Abc::IInt32ArrayProperty( _this, |
249 | 0 | ".creaseIndices", iArg0, iArg1 ); |
250 | 0 | } |
251 | |
|
252 | 0 | if ( this->getPropertyHeader(".creaseLengths") != NULL) |
253 | 0 | { |
254 | 0 | m_creaseLengthsProperty = Abc::IInt32ArrayProperty( _this, |
255 | 0 | ".creaseLengths", iArg0, iArg1 ); |
256 | 0 | } |
257 | |
|
258 | 0 | if ( this->getPropertyHeader(".creaseSharpnesses") != NULL) |
259 | 0 | { |
260 | 0 | m_creaseSharpnessesProperty = |
261 | 0 | Abc::IFloatArrayProperty( _this, |
262 | 0 | ".creaseSharpnesses", iArg0, iArg1 ); |
263 | 0 | } |
264 | |
|
265 | 0 | if ( this->getPropertyHeader(".cornerIndices") != NULL) |
266 | 0 | { |
267 | 0 | m_cornerIndicesProperty = |
268 | 0 | Abc::IInt32ArrayProperty( _this, ".cornerIndices", iArg0, iArg1 ); |
269 | 0 | } |
270 | |
|
271 | 0 | if ( this->getPropertyHeader(".cornerSharpnesses") != NULL) |
272 | 0 | { |
273 | 0 | m_cornerSharpnessesProperty = |
274 | 0 | Abc::IFloatArrayProperty( _this, ".cornerSharpnesses", |
275 | 0 | iArg0, iArg1 ); |
276 | 0 | } |
277 | |
|
278 | 0 | if ( this->getPropertyHeader(".holes") != NULL) |
279 | 0 | { |
280 | 0 | m_holesProperty = |
281 | 0 | Abc::IInt32ArrayProperty( _this, ".holes", iArg0, iArg1 ); |
282 | 0 | } |
283 | |
|
284 | 0 | if ( this->getPropertyHeader(".scheme") != NULL) |
285 | 0 | { |
286 | 0 | m_subdSchemeProperty = Abc::IStringProperty( _this, ".scheme", |
287 | 0 | iArg0, iArg1 ); |
288 | 0 | } |
289 | | |
290 | | // none of the things below here are guaranteed to exist |
291 | 0 | if ( this->getPropertyHeader( "uv" ) != NULL ) |
292 | 0 | { |
293 | 0 | m_uvsParam = IV2fGeomParam( _this, "uv", iArg0, iArg1 ); |
294 | 0 | } |
295 | |
|
296 | 0 | if ( this->getPropertyHeader( ".velocities" ) != NULL ) |
297 | 0 | { |
298 | 0 | m_velocitiesProperty = Abc::IV3fArrayProperty( _this, ".velocities", |
299 | 0 | iArg0, iArg1 ); |
300 | 0 | } |
301 | |
|
302 | 0 | m_faceSetsLoaded = false; |
303 | |
|
304 | 0 | ALEMBIC_ABC_SAFE_CALL_END_RESET(); |
305 | 0 | } |
306 | | |
307 | | //-***************************************************************************** |
308 | | void ISubDSchema::getFaceSetNames (std::vector <std::string> & oFaceSetNames) |
309 | 0 | { |
310 | 0 | ALEMBIC_ABC_SAFE_CALL_BEGIN( "ISubDSchema::getFaceSetNames()" ); |
311 | |
|
312 | 0 | Alembic::Util::scoped_lock l(m_faceSetsMutex); |
313 | 0 | loadFaceSetNames(); |
314 | |
|
315 | 0 | for (std::map<std::string, IFaceSet>::const_iterator faceSetIter = |
316 | 0 | m_faceSets.begin(); faceSetIter != m_faceSets.end(); ++faceSetIter) |
317 | 0 | { |
318 | 0 | oFaceSetNames.push_back( faceSetIter->first ); |
319 | 0 | } |
320 | |
|
321 | 0 | ALEMBIC_ABC_SAFE_CALL_END(); |
322 | 0 | } |
323 | | |
324 | | //-***************************************************************************** |
325 | | void ISubDSchema::loadFaceSetNames() |
326 | 0 | { |
327 | | // Caller must ensure they have locked m_faceSetsMutex. |
328 | | // (allows us to use non-recursive mutex) |
329 | 0 | ALEMBIC_ABC_SAFE_CALL_BEGIN( "ISubDSchema::loadFaceSetNames()" ); |
330 | |
|
331 | 0 | if (!m_faceSetsLoaded) |
332 | 0 | { |
333 | | // iterate over childHeaders, and if header matches |
334 | | // FaceSet add to our vec |
335 | 0 | IObject _thisObject = getObject(); |
336 | |
|
337 | 0 | size_t numChildren = _thisObject.getNumChildren(); |
338 | 0 | for ( size_t childIndex = 0 ; childIndex < numChildren; childIndex++ ) |
339 | 0 | { |
340 | 0 | ObjectHeader const & header = _thisObject.getChildHeader (childIndex); |
341 | 0 | if ( IFaceSet::matches( header ) ) |
342 | 0 | { |
343 | | // start out with an empty (invalid IFaceSet) |
344 | | // accessor later on will create real IFaceSet object. |
345 | 0 | m_faceSets [header.getName ()] = IFaceSet (); |
346 | 0 | } |
347 | 0 | } |
348 | 0 | m_faceSetsLoaded = true; |
349 | 0 | } |
350 | |
|
351 | 0 | ALEMBIC_ABC_SAFE_CALL_END(); |
352 | 0 | } |
353 | | |
354 | | //-***************************************************************************** |
355 | | bool |
356 | | ISubDSchema::hasFaceSet( const std::string &faceSetName ) |
357 | 0 | { |
358 | 0 | ALEMBIC_ABC_SAFE_CALL_BEGIN( "ISubDSchema::hasFaceSet (faceSetName)" ); |
359 | |
|
360 | 0 | Alembic::Util::scoped_lock l(m_faceSetsMutex); |
361 | 0 | if (!m_faceSetsLoaded) |
362 | 0 | { |
363 | 0 | loadFaceSetNames(); |
364 | 0 | } |
365 | |
|
366 | 0 | return (m_faceSets.find (faceSetName) != m_faceSets.end ()); |
367 | |
|
368 | 0 | ALEMBIC_ABC_SAFE_CALL_END(); |
369 | | |
370 | 0 | return false; |
371 | 0 | } |
372 | | |
373 | | //-***************************************************************************** |
374 | | IFaceSet |
375 | | ISubDSchema::getFaceSet( const std::string &iFaceSetName ) |
376 | 0 | { |
377 | 0 | ALEMBIC_ABC_SAFE_CALL_BEGIN( "ISubDSchema::getFaceSet()" ); |
378 | 0 | Alembic::Util::scoped_lock l(m_faceSetsMutex); |
379 | 0 | if (!m_faceSetsLoaded) |
380 | 0 | { |
381 | 0 | loadFaceSetNames(); |
382 | 0 | } |
383 | |
|
384 | 0 | ABCA_ASSERT( m_faceSets.find (iFaceSetName) != m_faceSets.end (), |
385 | 0 | "The requested FaceSet name can't be found in SubD."); |
386 | | |
387 | 0 | if (!m_faceSets [iFaceSetName]) |
388 | 0 | { |
389 | 0 | IObject thisObj = getObject(); |
390 | | // We haven't yet loaded the faceSet, so create/load it |
391 | 0 | m_faceSets [iFaceSetName] = IFaceSet ( thisObj, iFaceSetName ); |
392 | 0 | } |
393 | |
|
394 | 0 | return m_faceSets [iFaceSetName]; |
395 | |
|
396 | 0 | ALEMBIC_ABC_SAFE_CALL_END(); |
397 | | |
398 | 0 | IFaceSet empty; |
399 | 0 | return empty; |
400 | 0 | } |
401 | | |
402 | | } // End namespace ALEMBIC_VERSION_NS |
403 | | } // End namespace AbcGeom |
404 | | } // End namespace Alembic |