Coverage Report

Created: 2025-07-18 06:15

/src/alembic/lib/Alembic/AbcGeom/IXform.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/IXform.h>
38
#include <Alembic/AbcGeom/XformOp.h>
39
40
namespace Alembic {
41
namespace AbcGeom {
42
namespace ALEMBIC_VERSION_NS {
43
44
//-*****************************************************************************
45
void IXformSchema::init( const Abc::Argument &iArg0,
46
                         const Abc::Argument &iArg1 )
47
1
{
48
2
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IXformSchema::init()" );
49
50
2
    Abc::Arguments args;
51
2
    iArg0.setInto( args );
52
2
    iArg1.setInto( args );
53
54
2
    AbcA::CompoundPropertyReaderPtr ptr = this->getPtr();
55
56
2
    if ( ptr->getPropertyHeader( ".childBnds" ) )
57
0
    {
58
0
        m_childBoundsProperty = Abc::IBox3dProperty( ptr, ".childBnds",
59
0
                                                     iArg0, iArg1 );
60
0
    }
61
62
2
    if ( ptr->getPropertyHeader( ".inherits" ) )
63
0
    {
64
0
        m_inheritsProperty = Abc::IBoolProperty( ptr, ".inherits",
65
0
                                                 iArg0, iArg1 );
66
0
    }
67
68
2
    m_useArrayProp = false;
69
70
2
    const AbcA::PropertyHeader *valsPH = ptr->getPropertyHeader( ".vals" );
71
2
    if ( valsPH != NULL )
72
0
    {
73
0
        if ( valsPH->isScalar() )
74
0
        {
75
0
            m_valsProperty = ptr->getScalarProperty( valsPH->getName() );
76
0
        }
77
0
        else
78
0
        {
79
0
            m_useArrayProp = true;
80
0
            m_valsProperty = ptr->getArrayProperty( valsPH->getName() );
81
0
        }
82
0
    }
83
84
2
    m_isConstantIdentity = true;
85
86
2
    if ( ptr->getPropertyHeader( "isNotConstantIdentity" ) )
87
0
    {
88
        // that it's here at all means we're not constant identity.
89
0
        m_isConstantIdentity = false;
90
0
    }
91
92
2
    m_isConstant = true;
93
94
2
    if ( m_valsProperty )
95
0
    {
96
97
0
        if ( m_useArrayProp )
98
0
        { m_isConstant = m_valsProperty->asArrayPtr()->isConstant(); }
99
0
        else
100
0
        { m_isConstant = m_valsProperty->asScalarPtr()->isConstant(); }
101
0
    }
102
103
2
    m_isConstant = m_isConstant && ( !m_inheritsProperty ||
104
1
        m_inheritsProperty.isConstant() );
105
106
2
    std::set < Alembic::Util::uint32_t > animChannels;
107
108
2
    if ( ptr->getPropertyHeader( ".animChans" ) )
109
0
    {
110
0
        Abc::IUInt32ArrayProperty p( ptr, ".animChans" );
111
0
        if ( p.getNumSamples() > 0 )
112
0
        {
113
0
            Abc::UInt32ArraySamplePtr animSamp;
114
0
            p.get( animSamp, p.getNumSamples() - 1 );
115
0
            for ( std::size_t i = 0; i < animSamp->size(); ++i )
116
0
            {
117
0
                animChannels.insert( (*animSamp)[i] );
118
0
            }
119
0
        }
120
0
    }
121
122
2
    AbcA::ScalarPropertyReaderPtr ops;
123
2
    if ( ptr->getPropertyHeader( ".ops" ) != NULL )
124
0
    {
125
0
        ops = ptr->getScalarProperty( ".ops" );
126
0
    }
127
128
2
    if ( ops && ops->getNumSamples() > 0 )
129
0
    {
130
131
0
        std::size_t numOps = ops->getHeader().getDataType().getExtent();
132
0
        std::vector<Alembic::Util::uint8_t> opVec( numOps );
133
0
        ops->getSample( 0, &(opVec.front()) );
134
135
0
        for ( std::size_t i = 0; i < numOps; ++i )
136
0
        {
137
0
            XformOp op( opVec[i] );
138
0
            m_sample.addOp( op );
139
0
        }
140
141
0
        std::set < Alembic::Util::uint32_t >::iterator it, itEnd;
142
0
        std::vector< XformOp >::iterator op = m_sample.m_ops.begin();
143
0
        std::vector< XformOp >::iterator opEnd = m_sample.m_ops.end();
144
0
        std::size_t curChan = 0;
145
0
        std::size_t chanPos = 0;
146
147
0
        for ( it = animChannels.begin(), itEnd = animChannels.end();
148
0
            it != itEnd; ++it )
149
0
        {
150
0
            Alembic::Util::uint32_t animChan = *it;
151
0
            while ( op != opEnd )
152
0
            {
153
0
                std::size_t numChans = op->getNumChannels();
154
0
                bool foundChan = false;
155
0
                while ( curChan < numChans )
156
0
                {
157
0
                    if ( animChan == chanPos )
158
0
                    {
159
0
                        op->m_animChannels.insert( curChan );
160
0
                        foundChan = true;
161
0
                        break;
162
0
                    }
163
164
0
                    ++curChan;
165
0
                    ++chanPos;
166
0
                }
167
168
                // move on to the next animChan, because we found the current one
169
0
                if ( foundChan == true )
170
0
                {
171
0
                    ++curChan;
172
0
                    ++chanPos;
173
0
                    break;
174
0
                }
175
176
0
                ++op;
177
0
                curChan = 0;
178
0
            }
179
0
        }
180
0
    }
181
182
2
    if ( ptr->getPropertyHeader( ".arbGeomParams" ) != NULL )
183
0
    {
184
0
        m_arbGeomParams = Abc::ICompoundProperty( ptr, ".arbGeomParams",
185
0
                                                  args.getErrorHandlerPolicy()
186
0
                                                );
187
0
    }
188
189
2
    if ( ptr->getPropertyHeader( ".userProperties" ) != NULL )
190
0
    {
191
0
        m_userProperties = Abc::ICompoundProperty( ptr, ".userProperties",
192
0
                                                   args.getErrorHandlerPolicy()
193
0
                                                );
194
0
    }
195
2
    ALEMBIC_ABC_SAFE_CALL_END_RESET();
196
1
}
197
198
//-*****************************************************************************
199
AbcA::TimeSamplingPtr IXformSchema::getTimeSampling() const
200
0
{
201
0
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IXformSchema::getTimeSampling()" );
202
203
0
    if ( m_inheritsProperty )
204
0
    {
205
0
        return m_inheritsProperty.getTimeSampling();
206
0
    }
207
0
    else
208
0
    {
209
0
        return AbcA::TimeSamplingPtr( new AbcA::TimeSampling() );
210
0
    }
211
212
0
    ALEMBIC_ABC_SAFE_CALL_END();
213
214
0
    AbcA::TimeSamplingPtr ret;
215
0
    return ret;
216
0
}
217
218
//-*****************************************************************************
219
std::size_t IXformSchema::getNumSamples() const
220
1
{
221
2
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IXformSchema::getNumSamples()" );
222
223
2
    if ( m_inheritsProperty )
224
0
    {
225
0
        return m_inheritsProperty.getNumSamples();
226
0
    }
227
1
    else { return 0; }
228
229
2
    ALEMBIC_ABC_SAFE_CALL_END();
230
231
0
    return 0;
232
1
}
233
234
//-*****************************************************************************
235
void IXformSchema::getChannelValues( const AbcA::index_t iSampleIndex,
236
    XformSample & oSamp ) const
237
0
{
238
0
    std::vector<Alembic::Util::float64_t> dataVec;
239
240
0
    if ( m_useArrayProp )
241
0
    {
242
0
        AbcA::ArraySamplePtr sptr;
243
0
        m_valsProperty->asArrayPtr()->getSample( iSampleIndex, sptr );
244
245
0
        dataVec.assign(
246
0
            static_cast<const Alembic::Util::float64_t*>( sptr->getData() ),
247
0
            static_cast<const Alembic::Util::float64_t*>( sptr->getData() ) +
248
0
            sptr->size() );
249
0
    }
250
0
    else
251
0
    {
252
0
        dataVec.resize( m_valsProperty->asScalarPtr()->getDataType().getExtent() );
253
0
        m_valsProperty->asScalarPtr()->getSample( iSampleIndex, &(dataVec.front()) );
254
0
    }
255
256
0
    std::vector< XformOp >::iterator op = oSamp.m_ops.begin();
257
0
    std::vector< XformOp >::iterator opEnd = oSamp.m_ops.end();
258
0
    std::size_t chanPos = 0;
259
0
    while ( op != opEnd )
260
0
    {
261
0
        for ( std::size_t j = 0; j < op->getNumChannels();
262
0
            ++j, ++chanPos )
263
0
        {
264
0
            op->setChannelValue( j, dataVec[chanPos] );
265
0
        }
266
0
        ++op;
267
0
    }
268
0
}
269
270
//-*****************************************************************************
271
void IXformSchema::get( XformSample &oSamp, const Abc::ISampleSelector &iSS ) const
272
0
{
273
0
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IXformSchema::get()" );
274
275
0
    oSamp.reset();
276
277
0
    if ( ! valid() ) { return; }
278
279
0
    oSamp = m_sample;
280
281
0
    if ( m_inheritsProperty && m_inheritsProperty.getNumSamples() > 0 )
282
0
    {
283
0
        oSamp.setInheritsXforms( m_inheritsProperty.getValue( iSS ) );
284
0
    }
285
286
0
    if ( ! m_valsProperty ) { return; }
287
288
0
    AbcA::index_t numSamples = 0;
289
0
    if ( m_useArrayProp )
290
0
    {
291
0
        numSamples = m_valsProperty->asArrayPtr()->getNumSamples();
292
0
    }
293
0
    else
294
0
    {
295
0
        numSamples = m_valsProperty->asScalarPtr()->getNumSamples();
296
0
    }
297
298
0
    if ( numSamples == 0 ) { return; }
299
300
0
    AbcA::index_t sampIdx = iSS.getIndex( m_valsProperty->getTimeSampling(),
301
0
                                          numSamples );
302
303
0
    if ( sampIdx < 0 ) { return; }
304
305
0
    this->getChannelValues( sampIdx, oSamp );
306
307
0
    ALEMBIC_ABC_SAFE_CALL_END();
308
0
}
309
310
//-*****************************************************************************
311
XformSample IXformSchema::getValue( const Abc::ISampleSelector &iSS ) const
312
0
{
313
0
    XformSample ret;
314
0
    this->get( ret, iSS );
315
0
    return ret;
316
0
}
317
318
//-*****************************************************************************
319
bool IXformSchema::getInheritsXforms( const Abc::ISampleSelector &iSS ) const
320
0
{
321
0
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IXformSchema::getInheritsXforms()" );
322
323
0
    if ( ! m_inheritsProperty || m_inheritsProperty.getNumSamples() == 0 )
324
0
    {
325
0
        return true;
326
0
    }
327
328
0
    AbcA::index_t sampIdx = iSS.getIndex( m_inheritsProperty.getTimeSampling(),
329
0
                                          m_inheritsProperty.getNumSamples() );
330
331
0
    if ( sampIdx < 0 ) { return true; }
332
333
0
    return m_inheritsProperty.getValue( sampIdx );
334
335
0
    ALEMBIC_ABC_SAFE_CALL_END();
336
337
0
    return true;
338
0
}
339
340
} // End namespace ALEMBIC_VERSION_NS
341
} // End namespace AbcGeom
342
} // End namespace Alembic