Coverage Report

Created: 2025-08-29 06:10

/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