1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 //    names, trademarks, service marks, or product names of the Licensor
11 //    and its affiliates, except as required to comply with Section 4(c) of
12 //    the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 //     http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 /// \file alembicUtil.cpp
25 
26 #include "pxr/pxr.h"
27 #include "pxr/usd/plugin/usdAbc/alembicUtil.h"
28 #include "pxr/base/tf/ostreamMethods.h"
29 #include <Alembic/Abc/IArrayProperty.h>
30 #include <Alembic/Abc/IScalarProperty.h>
31 
32 PXR_NAMESPACE_OPEN_SCOPE
33 
34 
35 TF_DEFINE_PUBLIC_TOKENS(UsdAbc_AlembicContextFlagNames,
36                         USDABC_ALEMBIC_CONTEXT_FLAG_NAMES);
37 
38 namespace UsdAbc_AlembicUtil {
39 
40 using namespace ::Alembic::Abc;
41 
42 //
43 // Usd property value types.
44 //
45 
46 TF_DEFINE_PUBLIC_TOKENS(UsdAbcPrimTypeNames, USD_ABC_PRIM_TYPE_NAMES);
47 TF_DEFINE_PUBLIC_TOKENS(UsdAbcPropertyNames, USD_ABC_PROPERTY_NAMES);
48 TF_DEFINE_PUBLIC_TOKENS(UsdAbcCustomMetadata, USD_ABC_CUSTOM_METADATA);
49 
50 //
51 // UsdAbc_AlembicType
52 //
53 
54 std::string
Stringify() const55 UsdAbc_AlembicType::Stringify() const
56 {
57     if (extent == 1) {
58         return TfStringPrintf("%s%s", PODName(pod), array ? "[]" : "");
59     }
60     else {
61         return TfStringPrintf("%s[%d]%s",
62                               PODName(pod), extent, array ? "[]" : "");
63     }
64 }
65 
66 bool
operator ==(const UsdAbc_AlembicType & rhs) const67 UsdAbc_AlembicType::operator==(const UsdAbc_AlembicType& rhs) const
68 {
69     return pod    == rhs.pod &&
70            extent == rhs.extent &&
71            array  == rhs.array;
72 }
73 
74 bool
operator <(const UsdAbc_AlembicType & rhs) const75 UsdAbc_AlembicType::operator<(const UsdAbc_AlembicType& rhs) const
76 {
77     if (pod        < rhs.pod) {
78         return true;
79     }
80     if (rhs.pod    < pod) {
81         return false;
82     }
83     if (extent     < rhs.extent) {
84         return true;
85     }
86     if (rhs.extent < extent) {
87         return false;
88     }
89     return array < rhs.array;
90 }
91 
92 //
93 // Utilities
94 //
95 
96 /// Format an Alembic version number as a string.
97 std::string
UsdAbc_FormatAlembicVersion(int32_t n)98 UsdAbc_FormatAlembicVersion(int32_t n)
99 {
100     return TfStringPrintf("%d.%d.%d", n / 10000, (n / 100) % 100, n % 100);
101 }
102 
103 //
104 // POD property to/from Usd.
105 //
106 
107 template <class UsdType, class AlembicType, size_t extent>
108 struct _ConvertPODScalar {
operator ()UsdAbc_AlembicUtil::_ConvertPODScalar109     bool operator()(const ICompoundProperty& parent, const std::string& name,
110                     const ISampleSelector& iss,
111                     const UsdAbc_AlembicDataAny& dst) const
112     {
113         // Something to hold the sample.
114         AlembicType sample[extent];
115 
116         // Get the sample.
117         IScalarProperty property(parent, name);
118         property.get(sample, iss);
119 
120         // Copy to dst.
121         return dst.Set(_ConvertPODToUsd<UsdType, AlembicType,extent>()(sample));
122     }
123 
operator ()UsdAbc_AlembicUtil::_ConvertPODScalar124     _SampleForAlembic operator()(const VtValue& src) const
125     {
126         return _ConvertPODFromUsdScalar<UsdType, AlembicType, extent>()(src);
127     }
128 };
129 
130 template <class UsdType, class AlembicType, size_t extent>
131 struct _ConvertPODArray {
operator ()UsdAbc_AlembicUtil::_ConvertPODArray132     bool operator()(const ICompoundProperty& parent, const std::string& name,
133                     const ISampleSelector& iss,
134                     const UsdAbc_AlembicDataAny& dst) const
135     {
136         // Something to hold the sample.
137         ArraySamplePtr sample;
138 
139         // Get the sample.
140         IArrayProperty property(parent, name);
141         property.get(sample, iss);
142 
143         // Copy each element.
144         VtArray<UsdType> result(sample->size());
145         _ConvertPODToUsdArray<UsdType, AlembicType, extent>()(
146                 result.data(), sample->getData(), sample->size());
147 
148         // Copy to dst.
149         return dst.Set(result);
150     }
151 
operator ()UsdAbc_AlembicUtil::_ConvertPODArray152     _SampleForAlembic operator()(const VtValue& src) const
153     {
154         return _ConvertPODFromUsdArray<UsdType, AlembicType, extent>()(src);
155     }
156 };
157 
158 //
159 // _SampleForAlembic
160 //
161 
~_Holder()162 _SampleForAlembic::_Holder::~_Holder()
163 {
164     // Do nothing
165 }
166 
167 bool
Error(std::string * message) const168 _SampleForAlembic::_Holder::Error(std::string* message) const
169 {
170     if (message) {
171         message->clear();
172     }
173     return false;
174 }
175 
_EmptyHolder()176 _SampleForAlembic::_EmptyHolder::_EmptyHolder()
177 {
178     // Do nothing
179 }
180 
~_EmptyHolder()181 _SampleForAlembic::_EmptyHolder::~_EmptyHolder()
182 {
183     // Do nothing
184 }
185 
_ErrorHolder(const std::string & message)186 _SampleForAlembic::_ErrorHolder::_ErrorHolder(const std::string& message) :
187     _message(message)
188 {
189     // Do nothing
190 }
191 
192 bool
Error(std::string * message) const193 _SampleForAlembic::_ErrorHolder::Error(std::string* message) const
194 {
195     if (message) {
196         *message = _message;
197     }
198     return true;
199 }
200 
~_ErrorHolder()201 _SampleForAlembic::_ErrorHolder::~_ErrorHolder()
202 {
203     // Do nothing
204 }
205 
~_VtValueHolder()206 _SampleForAlembic::_VtValueHolder::~_VtValueHolder()
207 {
208     // Do nothing
209 }
210 
211 _SampleForAlembic
_ErrorSampleForAlembic(const std::string & msg)212 _ErrorSampleForAlembic(const std::string& msg)
213 {
214     return _SampleForAlembic(_SampleForAlembic::Error(msg));
215 }
216 
217 //
218 // Alembic <-> Usd conversion registries.
219 //
220 
221 //
222 // UsdAbc_AlembicDataConversion
223 //
224 
UsdAbc_AlembicDataConversion()225 UsdAbc_AlembicDataConversion::UsdAbc_AlembicDataConversion()
226 {
227     // Do nothing
228 }
229 
230 SdfValueTypeName
FindConverter(const UsdAbc_AlembicType & alembicType) const231 UsdAbc_AlembicDataConversion::FindConverter(
232     const UsdAbc_AlembicType& alembicType) const
233 {
234     for (const auto& c : _typeConverters) {
235         if (c.abcType == alembicType) {
236             return c.usdType;
237         }
238     }
239     return SdfValueTypeName();
240 }
241 
242 const UsdAbc_AlembicDataConversion::ToUsdConverter&
GetToUsdConverter(const UsdAbc_AlembicType & alembicType,const SdfValueTypeName & usdType) const243 UsdAbc_AlembicDataConversion::GetToUsdConverter(
244     const UsdAbc_AlembicType& alembicType,
245     const SdfValueTypeName &usdType) const
246 {
247     for (const auto& c : _typeConverters) {
248         if (c.usdType == usdType && c.abcType == alembicType) {
249             return c.toUsdFn;
250         }
251     }
252     static const ToUsdConverter empty;
253     return empty;
254 }
255 
256 UsdAbc_AlembicType
FindConverter(const SdfValueTypeName & usdType) const257 UsdAbc_AlembicDataConversion::FindConverter(
258     const SdfValueTypeName& usdType) const
259 {
260     for (const auto& c : _typeConverters) {
261         if (c.usdType == usdType) {
262             return c.abcType;
263         }
264     }
265     return UsdAbc_AlembicType();
266 }
267 
268 const UsdAbc_AlembicDataConversion::FromUsdConverter&
GetConverter(const SdfValueTypeName & usdType) const269 UsdAbc_AlembicDataConversion::GetConverter(
270     const SdfValueTypeName& usdType) const
271 {
272     for (const auto& c : _typeConverters) {
273         if (c.usdType == usdType) {
274             return c.fromUsdFn;
275         }
276     }
277 
278     static const FromUsdConverter empty;
279     return empty;
280 }
281 
282 void
_AddConverter(const UsdAbc_AlembicType & alembicType,const SdfValueTypeName & usdType,const ToUsdConverter & usdConverter,const FromUsdConverter & abcConverter)283 UsdAbc_AlembicDataConversion::_AddConverter(
284     const UsdAbc_AlembicType& alembicType,
285     const SdfValueTypeName& usdType,
286     const ToUsdConverter& usdConverter,
287     const FromUsdConverter& abcConverter)
288 {
289     _typeConverters.push_back(
290         _ConverterData(usdType, alembicType, usdConverter, abcConverter)
291     );
292 }
293 
UsdAbc_AlembicConversions()294 UsdAbc_AlembicConversions::UsdAbc_AlembicConversions()
295 {
296     // Preferred conversions.
297     data.AddConverter<bool,        bool_t>();
298     data.AddConverter<uint8_t,     uint8_t>();
299     data.AddConverter<int32_t,     int32_t>();
300     data.AddConverter<uint32_t,    uint32_t>();
301     data.AddConverter<int64_t,     int64_t>();
302     data.AddConverter<uint64_t,    uint64_t>();
303     data.AddConverter<GfHalf,      ::half>();
304     data.AddConverter<float,       float32_t>();
305     data.AddConverter<double,      float64_t>();
306     data.AddConverter<std::string, std::string>();
307     data.AddConverter<GfVec2i,   int32_t, 2>();
308     data.AddConverter<GfVec2h,    GfHalf, 2>();
309     data.AddConverter<GfVec2f, float32_t, 2>();
310     data.AddConverter<GfVec2d, float64_t, 2>();
311     data.AddConverter<GfVec3i,   int32_t, 3>();
312     data.AddConverter<GfVec3h,    GfHalf, 3>();
313     data.AddConverter<GfVec3f, float32_t, 3>();
314     data.AddConverter<GfVec3d, float64_t, 3>();
315     data.AddConverter<GfVec4i,   int32_t, 4>();
316     data.AddConverter<GfVec4h,    GfHalf, 4>();
317     data.AddConverter<GfVec4f, float32_t, 4>();
318     data.AddConverter<GfVec4d, float64_t, 4>();
319     data.AddConverter<GfQuatf, float32_t, 4>();
320     data.AddConverter<GfQuatd, float64_t, 4>();
321     data.AddConverter<GfMatrix4d, float64_t, 16>();
322 
323     // Other conversions.
324     data.AddConverter<int,          int8_t>();
325     data.AddConverter<int,          int16_t>();
326     data.AddConverter<unsigned int, uint16_t>();
327     data.AddConverter<TfToken,      std::string>();
328     data.AddConverter<GfMatrix4d,   float32_t, 16>();
329 
330     // Role conversions.
331     data.AddConverter<GfVec3h,    GfHalf, 3>(SdfValueTypeNames->Point3h);
332     data.AddConverter<GfVec3f, float32_t, 3>(SdfValueTypeNames->Point3f);
333     data.AddConverter<GfVec3d, float64_t, 3>(SdfValueTypeNames->Point3d);
334     data.AddConverter<GfVec3h,    GfHalf, 3>(SdfValueTypeNames->Normal3h);
335     data.AddConverter<GfVec3f, float32_t, 3>(SdfValueTypeNames->Normal3f);
336     data.AddConverter<GfVec3d, float64_t, 3>(SdfValueTypeNames->Normal3d);
337     data.AddConverter<GfVec3h,    GfHalf, 3>(SdfValueTypeNames->Vector3h);
338     data.AddConverter<GfVec3f, float32_t, 3>(SdfValueTypeNames->Vector3f);
339     data.AddConverter<GfVec3d, float64_t, 3>(SdfValueTypeNames->Vector3d);
340     data.AddConverter<GfVec3h,    GfHalf, 3>(SdfValueTypeNames->Color3h);
341     data.AddConverter<GfVec3f, float32_t, 3>(SdfValueTypeNames->Color3f);
342     data.AddConverter<GfVec3d, float64_t, 3>(SdfValueTypeNames->Color3d);
343     data.AddConverter<GfMatrix4d, float64_t, 16>(SdfValueTypeNames->Frame4d);
344     data.AddConverter<GfVec2f, float32_t, 2>(SdfValueTypeNames->TexCoord2f);
345 }
346 
347 } // namespace UsdAbc_AlembicUtil
348 
349 PXR_NAMESPACE_CLOSE_SCOPE
350 
351