Coverage Report

Created: 2025-08-29 06:10

/src/alembic/lib/Alembic/AbcGeom/OCurves.h
Line
Count
Source (jump to first uncovered line)
1
//-*****************************************************************************
2
//
3
// Copyright (c) 2009-2013,
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
#ifndef Alembic_AbcGeom_OCurves_h
38
#define Alembic_AbcGeom_OCurves_h
39
40
#include <Alembic/Util/Export.h>
41
#include <Alembic/AbcGeom/Foundation.h>
42
#include <Alembic/AbcGeom/Basis.h>
43
#include <Alembic/AbcGeom/CurveType.h>
44
#include <Alembic/AbcGeom/SchemaInfoDeclarations.h>
45
#include <Alembic/AbcGeom/OGeomParam.h>
46
#include <Alembic/AbcGeom/OGeomBase.h>
47
48
namespace Alembic {
49
namespace AbcGeom {
50
namespace ALEMBIC_VERSION_NS {
51
52
//-*****************************************************************************
53
// Curves definition - Similar in form to the Geometric primitive used to
54
// specify curves in renderman.
55
// "type"   - linear or cubic, one type for all curves
56
// "wrap"   - periodic or nonperiodic, one mode for all curves
57
// ---
58
// "P"      - vertexes for the curves being written
59
// "width"  - can be constant or can vary
60
// "N"      - (just like PolyMesh, via a geom parameter) Normals
61
// "uv"     - (just like PolyMesh, via a geom parameter) u-v coordinates
62
class ALEMBIC_EXPORT OCurvesSchema : public OGeomBaseSchema<CurvesSchemaInfo>
63
{
64
public:
65
    //-*************************************************************************
66
    // CURVE SCHEMA SAMPLE TYPE
67
    //-*************************************************************************
68
    class Sample
69
    {
70
    public:
71
        //! Creates a default sample with no data in it.
72
        //! ...
73
        Sample()
74
0
        {
75
0
            // even though this might not be written out
76
0
            // (unless curvesNumVertices and points is set) give some reasonable
77
0
            // and predictable defaults
78
0
            reset();
79
0
            m_type = kCubic;
80
0
            m_wrap = kNonPeriodic;
81
0
            m_basis = kBezierBasis;
82
0
        }
83
84
        //! Creates a sample with position data but no index
85
        //! or count data. For specifying samples after the first one
86
        Sample( const Abc::P3fArraySample &iPos )
87
          : m_positions( iPos )
88
0
        {
89
0
            // even though this might not be written out
90
0
            // (unless curvesNumVertices is set) give some reasonable
91
0
            // and predictable defaults
92
0
            m_type = kCubic;
93
0
            m_wrap = kNonPeriodic;
94
0
            m_basis = kBezierBasis;
95
0
        }
96
97
98
        //! Creates a sample with position data, index data, count data,
99
        //! and optional UV and Normals data.
100
        //! For specifying samples with an explicit topology. The first
101
        //! sample must be full like this. Subsequent samples may also
102
        //! be full like this, which would indicate a change of topology
103
        Sample(
104
                const Abc::P3fArraySample &iPos,
105
                const Abc::Int32ArraySample &iNVertices,
106
                const CurveType &iType = kCubic,
107
                const CurvePeriodicity iWrap = kNonPeriodic,
108
                const OFloatGeomParam::Sample &iWidths = \
109
                OFloatGeomParam::Sample(),
110
                const OV2fGeomParam::Sample &iUVs = OV2fGeomParam::Sample(),
111
                const ON3fGeomParam::Sample &iNormals = ON3fGeomParam::Sample(),
112
                const BasisType &iBasis = kBezierBasis,
113
                const Abc::FloatArraySample &iPosWeight = \
114
                Abc::FloatArraySample(),
115
                const Abc::UcharArraySample &iOrders = Abc::UcharArraySample(),
116
                const Abc::FloatArraySample &iKnots = Abc::FloatArraySample()
117
        ): m_positions( iPos ),
118
            m_nVertices( iNVertices ),
119
            m_type( iType ),
120
            m_wrap( iWrap ),
121
            m_widths( iWidths ),
122
            m_uvs( iUVs ),
123
            m_normals( iNormals ),
124
            m_basis( iBasis ),
125
            m_positionWeights( iPosWeight ),
126
            m_orders( iOrders ),
127
0
            m_knots( iKnots ) {}
128
129
        // widths accessor
130
0
        const OFloatGeomParam::Sample &getWidths() const { return m_widths; }
131
        void setWidths( const OFloatGeomParam::Sample &iWidths )
132
0
        { m_widths = iWidths; }
133
134
        // positions accessor
135
0
        const Abc::P3fArraySample &getPositions() const { return m_positions; }
136
        void setPositions( const Abc::P3fArraySample &iSmp )
137
0
        { m_positions = iSmp; }
138
139
        // position weights, if it isn't set, it's 1 for every point
140
        const Abc::FloatArraySample &getPositionWeights() const
141
0
        { return m_positionWeights; }
142
        void setPositionWeights(  const Abc::FloatArraySample &iSmp )
143
0
        { m_positionWeights = iSmp; }
144
145
        // type accessors
146
        void setType( const CurveType &iType )
147
0
        { m_type = iType; }
148
0
        CurveType getType() const { return m_type; }
149
150
        // wrap accessors
151
        void setWrap( const CurvePeriodicity &iWrap )
152
0
        { m_wrap = iWrap; }
153
0
        CurvePeriodicity getWrap() const { return m_wrap; }
154
155
0
        std::size_t getNumCurves() const { return m_nVertices.size(); }
156
157
        //! an array of ints that corresponds to the number
158
        //! of vertices per curve
159
        void setCurvesNumVertices( const Abc::Int32ArraySample &iNVertices)
160
0
        { m_nVertices = iNVertices; }
161
        const Abc::Int32ArraySample &getCurvesNumVertices() const
162
0
        { return m_nVertices; }
163
164
        // UVs
165
0
        const OV2fGeomParam::Sample &getUVs() const { return m_uvs; }
166
        void setUVs( const OV2fGeomParam::Sample &iUVs )
167
0
        { m_uvs = iUVs; }
168
169
        // bounding box accessors
170
0
        const Abc::Box3d &getSelfBounds() const { return m_selfBounds; }
171
        void setSelfBounds( const Abc::Box3d &iBnds )
172
0
        { m_selfBounds = iBnds; }
173
174
        // velocities accessor
175
0
        const Abc::V3fArraySample &getVelocities() const { return m_velocities; }
176
        void setVelocities( const Abc::V3fArraySample &iVelocities )
177
0
        { m_velocities = iVelocities; }
178
179
        // normal accessors
180
0
        const ON3fGeomParam::Sample &getNormals() const { return m_normals; }
181
        void setNormals( const ON3fGeomParam::Sample &iNormals )
182
0
        { m_normals = iNormals; }
183
184
        // basis accessors
185
0
        BasisType getBasis() const { return m_basis; }
186
        void setBasis( const BasisType &iBasis )
187
0
        { m_basis = iBasis; }
188
189
        // orders accessors
190
0
        const Abc::UcharArraySample &getOrders() const { return m_orders; }
191
        void setOrders( const Abc::UcharArraySample &iOrders)
192
0
        { m_orders = iOrders; }
193
194
        // knot accessors
195
0
        const Abc::FloatArraySample &getKnots() const { return m_knots; }
196
        void setKnots( const Abc::FloatArraySample &iKnots)
197
0
        { m_knots = iKnots; }
198
199
        void reset()
200
0
        {
201
0
            m_positions.reset();
202
0
            m_positionWeights.reset();
203
0
            m_velocities.reset();
204
0
            m_uvs.reset();
205
0
            m_normals.reset();
206
0
            m_widths.reset();
207
0
208
0
            m_nVertices.reset();
209
0
210
0
            m_orders.reset();
211
0
            m_knots.reset();
212
0
213
0
            m_selfBounds.makeEmpty();
214
0
215
0
            m_type = kCubic;
216
0
            m_wrap = kNonPeriodic;
217
0
            m_basis = kBezierBasis;
218
0
        }
219
220
        bool isPartialSample() const
221
0
        {
222
0
            if( !m_positions.getData() )
223
0
            {
224
0
                if( m_uvs.getVals() || m_normals.getVals() || m_velocities.getData() )
225
0
                {
226
0
                    return true;
227
0
                }
228
0
            }
229
0
230
0
            return false;
231
0
        }
232
233
    protected:
234
235
        // properties
236
        Abc::P3fArraySample m_positions;
237
        Abc::V3fArraySample m_velocities;
238
        Abc::Int32ArraySample m_nVertices;
239
240
        CurveType m_type;
241
        CurvePeriodicity m_wrap;
242
243
        OFloatGeomParam::Sample m_widths;
244
        OV2fGeomParam::Sample m_uvs;
245
        ON3fGeomParam::Sample m_normals;
246
247
        BasisType m_basis;
248
249
        // optional properties
250
        Abc::FloatArraySample m_positionWeights;
251
        Abc::UcharArraySample m_orders;
252
        Abc::FloatArraySample m_knots;
253
254
        // bounding box attributes
255
        Abc::Box3d m_selfBounds;
256
257
    };
258
259
    //-*************************************************************************
260
    // CURVE SCHEMA
261
    //-*************************************************************************
262
263
public:
264
265
    //! By convention we always define this_type in AbcGeom classes.
266
    //! Used by unspecified-bool-type conversion below
267
    typedef OCurvesSchema this_type;
268
    typedef OCurvesSchema::Sample sample_type;
269
270
    //-*************************************************************************
271
    // CONSTRUCTION, DESTRUCTION, ASSIGNMENT
272
    //-*************************************************************************
273
274
    //! The default constructor creates an empty OCurvesSchema
275
    //! ...
276
    OCurvesSchema()
277
0
    {
278
0
        m_selectiveExport = false;
279
0
        m_numSamples = 0;
280
0
        m_timeSamplingIndex = 0;
281
0
    }
282
283
284
    //! This constructor creates a new curves writer.
285
    //! The first argument is the compound property to use as a parent
286
    //! The remaining optional arguments are the parents ErrorHandlerPolicy,
287
    //! an override to the ErrorHandlerPolicy, MetaData, and TimeSampling info.
288
    OCurvesSchema( AbcA::CompoundPropertyWriterPtr iParent,
289
                   const std::string &iName,
290
                   const Abc::Argument &iArg0 = Abc::Argument(),
291
                   const Abc::Argument &iArg1 = Abc::Argument(),
292
                   const Abc::Argument &iArg2 = Abc::Argument(),
293
                   const Abc::Argument &iArg3 = Abc::Argument() )
294
      : OGeomBaseSchema<CurvesSchemaInfo>( iParent, iName,
295
                                           iArg0, iArg1, iArg2, iArg3)
296
0
    {
297
0
        // Meta data and error handling are eaten up by
298
0
        // the super type, so all that's left is time sampling.
299
0
        AbcA::TimeSamplingPtr tsPtr =
300
0
            Abc::GetTimeSampling( iArg0, iArg1, iArg2, iArg3 );
301
0
302
0
        AbcA::index_t tsIndex =
303
0
            Abc::GetTimeSamplingIndex( iArg0, iArg1, iArg2, iArg3 );
304
0
305
0
        if ( tsPtr )
306
0
        {
307
0
            tsIndex = GetCompoundPropertyWriterPtr( iParent )->getObject(
308
0
                )->getArchive()->addTimeSampling( *tsPtr );
309
0
        }
310
0
311
0
        init( tsIndex, Abc::IsSparse( iArg0, iArg1, iArg2, iArg3 ) );
312
0
    }
313
314
    //! Default assignment and copy operator used.
315
316
    //-*************************************************************************
317
    // SCHEMA STUFF
318
    //-*************************************************************************
319
320
    //! Return the time sampling type, which is stored on each of the
321
    //! sub properties.
322
    AbcA::TimeSamplingPtr getTimeSampling() const
323
0
    {
324
0
        if( m_positionsProperty.valid() )
325
0
        {
326
0
            return m_positionsProperty.getTimeSampling();
327
0
        }
328
0
        else
329
0
        {
330
0
            return getObject().getArchive().getTimeSampling( 0 );
331
0
        }
332
0
    }
333
334
    void setTimeSampling( uint32_t iIndex );
335
    void setTimeSampling( AbcA::TimeSamplingPtr iTime );
336
337
    //-*************************************************************************
338
    // SAMPLE STUFF
339
    //-*************************************************************************
340
341
    //! Get number of samples written so far.
342
    //! ...
343
0
    size_t getNumSamples() const { return m_numSamples; }
344
345
    //! Set a sample! Sample zero has to have non-degenerate
346
    //! positions, indices and counts.
347
    void set( const sample_type &iSamp );
348
349
    //! Set from previous sample. Will apply to each of positions,
350
    //! indices, and counts.
351
    void setFromPrevious();
352
353
    //-*************************************************************************
354
    // ABC BASE MECHANISMS
355
    // These functions are used by Abc to deal with errors, validity,
356
    // and so on.
357
    //-*************************************************************************
358
359
    //! Reset returns this function set to an empty, default
360
    //! state.
361
    void reset()
362
0
    {
363
0
        m_positionsProperty.reset();
364
0
        m_positionWeightsProperty.reset();
365
0
        m_uvsParam.reset();
366
0
        m_normalsParam.reset();
367
0
        m_widthsParam.reset();
368
0
        m_nVerticesProperty.reset();
369
0
        m_ordersProperty.reset();
370
0
        m_knotsProperty.reset();
371
0
372
0
        m_basisAndTypeProperty.reset();
373
0
374
0
        OGeomBaseSchema<CurvesSchemaInfo>::reset();
375
0
    }
376
377
    //! Valid returns whether this function set is
378
    //! valid.
379
    bool valid() const
380
0
    {
381
0
        return ( ( OGeomBaseSchema<CurvesSchemaInfo>::valid() &&
382
0
                     m_positionsProperty.valid() )
383
0
                 || m_selectiveExport );
384
0
    }
385
386
    //! unspecified-bool-type operator overload.
387
    //! ...
388
    ALEMBIC_OVERRIDE_OPERATOR_BOOL( this_type::valid() );
389
390
private:
391
    void init( const AbcA::index_t iTsIdx, bool isSparse );
392
393
    //! Set only some property data. Does not need to be a valid schema sample
394
    //! This is to be used when created a file which will be layered in to
395
    //! another file.
396
    void selectiveSet( const Sample &iSamp );
397
398
    // point data
399
    Abc::OP3fArrayProperty m_positionsProperty;
400
    Abc::OInt32ArrayProperty m_nVerticesProperty;
401
402
    // Write out only some properties (UVs, normals).
403
    // This is to export data to layer into another file later.
404
    bool m_selectiveExport;
405
406
    // Number of times OPolyMeshSchema::set() has been called
407
    size_t m_numSamples;
408
409
    uint32_t m_timeSamplingIndex;
410
411
    void createPositionProperty();
412
    void createVertexProperties();
413
    void createVelocityProperty();
414
    void createUVsProperty( const Sample &iSamp );
415
    void createNormalsProperty( const Sample &iSamp );
416
    void createWidthProperty( const Sample &iSamp );
417
    void createPositionWeightsProperty();
418
    void createOrdersProperty();
419
    void createKnotsProperty();
420
    void calcBasisAndType(Alembic::Util::uint8_t (&basisAndType)[4], const Sample &iSamp);
421
422
    // optional data
423
    OV2fGeomParam m_uvsParam;
424
    ON3fGeomParam m_normalsParam;
425
    OFloatGeomParam m_widthsParam;
426
    Abc::OV3fArrayProperty m_velocitiesProperty;
427
    Abc::OFloatArrayProperty m_positionWeightsProperty;
428
    Abc::OUcharArrayProperty m_ordersProperty;
429
    Abc::OFloatArrayProperty m_knotsProperty;
430
431
    Abc::OScalarProperty m_basisAndTypeProperty;
432
};
433
434
//-*****************************************************************************
435
// SCHEMA OBJECT
436
//-*****************************************************************************
437
typedef Abc::OSchemaObject<OCurvesSchema> OCurves;
438
439
typedef Util::shared_ptr< OCurves > OCurvesPtr;
440
441
} // End namespace ALEMBIC_VERSION_NS
442
443
using namespace ALEMBIC_VERSION_NS;
444
445
} // End namespace AbcGeom
446
} // End namespace Alembic
447
448
#endif