1#!/pxrpythonsubst
2#
3# Copyright 2018 Pixar
4#
5# Licensed under the Apache License, Version 2.0 (the "Apache License")
6# with the following modification; you may not use this file except in
7# compliance with the Apache License and the following modification to it:
8# Section 6. Trademarks. is deleted and replaced with:
9#
10# 6. Trademarks. This License does not grant permission to use the trade
11#    names, trademarks, service marks, or product names of the Licensor
12#    and its affiliates, except as required to comply with Section 4(c) of
13#    the License and to reproduce the content of the NOTICE file.
14#
15# You may obtain a copy of the Apache License at
16#
17#     http://www.apache.org/licenses/LICENSE-2.0
18#
19# Unless required by applicable law or agreed to in writing, software
20# distributed under the Apache License with the above modification is
21# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
22# KIND, either express or implied. See the Apache License for the specific
23# language governing permissions and limitations under the Apache License.
24
25from pxr import UsdUtils, Usd, Sdf, UsdGeom, Gf, Tf
26
27import unittest
28
29class TestUsdUtilsSparseAuthoring(unittest.TestCase):
30    def TestAttrOfType(self, typeName, arrayTypeName, defaultValue, epsilon):
31        s = Usd.Stage.CreateInMemory()
32        scope = UsdGeom.Scope.Define(s, "/Scope")
33
34        # Test scalar valued attribute.
35        attr = scope.GetPrim().CreateAttribute("attr", typeName)
36        self.assertFalse(attr.HasAuthoredValue())
37
38        valueWriter = UsdUtils.SparseAttrValueWriter(attr,
39                defaultValue=defaultValue)
40        self.assertTrue(attr.HasAuthoredValue())
41
42        valueType = type(defaultValue)
43        valueWriter.SetTimeSample(value=valueType(10.), time=0.0)
44        valueWriter.SetTimeSample(value=valueType(10.), time=0.5)
45        valueWriter.SetTimeSample(value=valueType(10.), time=1.0)
46        valueWriter.SetTimeSample(value=valueType(20.), time=2.0)
47        valueWriter.SetTimeSample(value=valueType(20.), time=3.0)
48        valueWriter.SetTimeSample(value=valueType(20.), time=4.0)
49        valueWriter.SetTimeSample(value=valueType(30.), time=5.0)
50        valueWriter.SetTimeSample(value=valueType(30. + (epsilon / 2)),
51                                  time=6.0)
52        valueWriter.SetTimeSample(value=valueType(30.), time=7.0)
53        valueWriter.SetTimeSample(value=valueType(30. + (epsilon * 2)),
54                                  time=8.0)
55        expectedTimeSamples = [1.0, 2.0, 4.0, 5.0, 7.0, 8.0] if \
56                              defaultValue == valueType(10.0) else \
57                              [0.0, 1.0, 2.0, 4.0, 5.0, 7.0, 8.0]
58        self.assertEqual(attr.GetTimeSamples(), expectedTimeSamples)
59
60        # Test array valued attribute.
61        arrayAttr = scope.GetPrim().CreateAttribute("arrayAttr", arrayTypeName)
62        self.assertFalse(arrayAttr.HasAuthoredValue())
63
64        arrayValueWriter = UsdUtils.SparseAttrValueWriter(arrayAttr,
65                defaultValue=[defaultValue, defaultValue])
66        self.assertTrue(arrayAttr.HasAuthoredValue())
67
68        arrayValueWriter.SetTimeSample(value=[valueType(10.), valueType(10.)],
69                                       time=0.0)
70        arrayValueWriter.SetTimeSample(value=[valueType(10.), valueType(10.)],
71                                       time=0.5)
72        arrayValueWriter.SetTimeSample(value=[valueType(10.), valueType(10.)],
73                                       time=1.0)
74        arrayValueWriter.SetTimeSample(value=[valueType(20.), valueType(10.)],
75                                       time=2.0)
76        arrayValueWriter.SetTimeSample(value=[valueType(20.), valueType(10.)],
77                                       time=3.0)
78        arrayValueWriter.SetTimeSample(value=[valueType(20.), valueType(10.)],
79                                       time=4.0)
80        arrayValueWriter.SetTimeSample(value=[valueType(30.), valueType(30.)],
81                                       time=5.0)
82        arrayValueWriter.SetTimeSample(value=[valueType(30.),
83                                       valueType(30. + (epsilon / 2))],
84                                       time=6.0)
85        arrayValueWriter.SetTimeSample(value=[valueType(30.), valueType(30.)],
86                                       time=7.0)
87        arrayValueWriter.SetTimeSample(value=[valueType(30. + (epsilon * 2)),
88                                       valueType(30.)],
89                                       time=8.0)
90
91        expectedTimeSamples = [1.0, 2.0, 4.0, 5.0, 7.0, 8.0] if \
92                              defaultValue == valueType(10.0) else \
93                              [0.0, 1.0, 2.0, 4.0, 5.0, 7.0, 8.0]
94        self.assertEqual(attr.GetTimeSamples(), expectedTimeSamples)
95
96    def test_Double(self):
97        self.TestAttrOfType(Sdf.ValueTypeNames.Double,
98            Sdf.ValueTypeNames.DoubleArray, 0.0, 1e-12)
99
100    def test_Float(self):
101        # default value matches first time-sample.
102        self.TestAttrOfType(Sdf.ValueTypeNames.Float,
103            Sdf.ValueTypeNames.FloatArray, 10.0, 1e-6)
104
105    def test_Half(self):
106        self.TestAttrOfType(Sdf.ValueTypeNames.Half,
107            Sdf.ValueTypeNames.HalfArray, 20.0, 1e-2)
108
109    def test_Vectors(self):
110        self.TestAttrOfType(Sdf.ValueTypeNames.Float2,
111            Sdf.ValueTypeNames.Float2Array, Gf.Vec2f(0.0), 1e-6)
112        self.TestAttrOfType(Sdf.ValueTypeNames.Float3,
113            Sdf.ValueTypeNames.Float3Array, Gf.Vec3f(0.0), 1e-6)
114        self.TestAttrOfType(Sdf.ValueTypeNames.Float4,
115            Sdf.ValueTypeNames.Float4Array, Gf.Vec4f(0.0), 1e-6)
116
117        self.TestAttrOfType(Sdf.ValueTypeNames.Double2,
118            Sdf.ValueTypeNames.Double2Array, Gf.Vec2d(0.0), 1e-12)
119        self.TestAttrOfType(Sdf.ValueTypeNames.Double3,
120            Sdf.ValueTypeNames.Double3Array, Gf.Vec3d(0.0), 1e-12)
121        self.TestAttrOfType(Sdf.ValueTypeNames.Double4,
122            Sdf.ValueTypeNames.Double4Array, Gf.Vec4d(0.0), 1e-12)
123
124        self.TestAttrOfType(Sdf.ValueTypeNames.Half2,
125            Sdf.ValueTypeNames.Half2Array, Gf.Vec2h(0.0), 1e-2)
126        self.TestAttrOfType(Sdf.ValueTypeNames.Half3,
127            Sdf.ValueTypeNames.Half3Array, Gf.Vec3h(0.0), 1e-2)
128        self.TestAttrOfType(Sdf.ValueTypeNames.Half4,
129            Sdf.ValueTypeNames.Half4Array, Gf.Vec4h(0.0), 1e-2)
130
131    def test_Matrices(self):
132        self.TestAttrOfType(Sdf.ValueTypeNames.Matrix2d,
133            Sdf.ValueTypeNames.Matrix2dArray, Gf.Matrix2d(0.0), 1e-12)
134        self.TestAttrOfType(Sdf.ValueTypeNames.Matrix3d,
135            Sdf.ValueTypeNames.Matrix3dArray, Gf.Matrix3d(0.0), 1e-12)
136        self.TestAttrOfType(Sdf.ValueTypeNames.Matrix4d,
137            Sdf.ValueTypeNames.Matrix4dArray, Gf.Matrix4d(0.0), 1e-12)
138
139    def TestQuats(self, typeName, arrayTypeName, defaultValue, epsilon):
140        s = Usd.Stage.CreateInMemory()
141        scope = UsdGeom.Scope.Define(s, "/Scope")
142
143        # Test scalar valued quat attribute.
144        attr = scope.GetPrim().CreateAttribute("quat", typeName)
145        self.assertFalse(attr.HasAuthoredValue())
146
147        valueWriter = UsdUtils.SparseAttrValueWriter(attr,
148                defaultValue=defaultValue)
149        self.assertTrue(attr.HasAuthoredValue())
150
151        valueType = type(defaultValue)
152        realType = type(defaultValue.GetReal())
153        imaginaryType = type(defaultValue.GetImaginary())
154
155        valueWriter.SetTimeSample(value=valueType(realType(10.),
156                                                  imaginaryType(10.0)),
157                                  time=1.0)
158        valueWriter.SetTimeSample(value=valueType(realType(20.),
159                                                  imaginaryType(20.0)),
160                                  time=2.0)
161        valueWriter.SetTimeSample(value=valueType(realType(20.),
162                                                  imaginaryType(20.0)),
163                                  time=3.0)
164        valueWriter.SetTimeSample(value=valueType(realType(20.),
165                                                  imaginaryType(20.0)),
166                                  time=4.0)
167        valueWriter.SetTimeSample(value=valueType(realType(30.),
168                                                  imaginaryType(30.0)),
169                                  time=5.0)
170        valueWriter.SetTimeSample(value=valueType(realType(30. + epsilon / 2),
171                                    imaginaryType(30.0 + epsilon / 2)),
172                                  time=6.0)
173        valueWriter.SetTimeSample(value=valueType(realType(30.),
174                                                  imaginaryType(30.0)),
175                                  time=7.0)
176        valueWriter.SetTimeSample(value=valueType(realType(30. + epsilon * 2),
177                                    imaginaryType(30.0 + epsilon * 2)),
178                                  time=8.0)
179
180        self.assertEqual(attr.GetTimeSamples(),
181                         [1.0, 2.0, 4.0, 5.0, 7.0, 8.0])
182
183
184        # Test array valued quats.
185        arrayAttr = scope.GetPrim().CreateAttribute("arrayQuat", arrayTypeName)
186        self.assertFalse(arrayAttr.HasAuthoredValue())
187
188        arrayValueWriter = UsdUtils.SparseAttrValueWriter(arrayAttr,
189                defaultValue=[defaultValue, defaultValue])
190        self.assertTrue(arrayAttr.HasAuthoredValue())
191
192        arrayValueWriter.SetTimeSample(
193                value=[valueType(realType(10.), imaginaryType(10.0)),
194                       valueType(realType(10.), imaginaryType(10.0))],
195                time=1.0)
196        arrayValueWriter.SetTimeSample(
197                value=[valueType(realType(20.), imaginaryType(10.0)),
198                       valueType(realType(10.), imaginaryType(20.0))],
199                time=2.0)
200        arrayValueWriter.SetTimeSample(
201                value=[valueType(realType(20.), imaginaryType(10.0)),
202                       valueType(realType(10.), imaginaryType(20.0))],
203                time=3.0)
204        arrayValueWriter.SetTimeSample(
205                value=[valueType(realType(20.), imaginaryType(10.0)),
206                       valueType(realType(10.), imaginaryType(20.0))],
207                time=4.0)
208        arrayValueWriter.SetTimeSample(
209                value=[valueType(realType(30.), imaginaryType(30.0)),
210                       valueType(realType(30.), imaginaryType(30.0))],
211                time=5.0)
212        arrayValueWriter.SetTimeSample(
213                value=[valueType(realType(30. + epsilon/2),
214                                 imaginaryType(30.0 + epsilon/2)),
215                       valueType(realType(30.+ epsilon/2),
216                                 imaginaryType(30.0 + epsilon/2))],
217                time=6.0)
218        arrayValueWriter.SetTimeSample(
219                value=[valueType(realType(30.), imaginaryType(30.0)),
220                       valueType(realType(30.), imaginaryType(30.0))],
221                time=7.0)
222        arrayValueWriter.SetTimeSample(
223                value=[valueType(realType(30.),
224                                 imaginaryType(30.0 + epsilon*2)),
225                       valueType(realType(30.+ epsilon*2),
226                                 imaginaryType(30.0))],
227                time=8.0)
228
229        expectedTimeSamples = [1.0, 2.0, 4.0, 5.0, 7.0, 8.0]
230        self.assertEqual(attr.GetTimeSamples(), expectedTimeSamples)
231
232    def test_testQuats(self):
233        self.TestQuats(Sdf.ValueTypeNames.Quatd,
234                       Sdf.ValueTypeNames.QuatdArray,
235                       Gf.Quatd(0.0), 1e-12)
236        self.TestQuats(Sdf.ValueTypeNames.Quatf,
237                       Sdf.ValueTypeNames.QuatfArray,
238                       Gf.Quatf(0.0), 1e-6)
239        self.TestQuats(Sdf.ValueTypeNames.Quath,
240                       Sdf.ValueTypeNames.QuathArray,
241                       Gf.Quath(0.0), 1e-2)
242
243    def test_MatchDefault(self):
244        s = Usd.Stage.CreateInMemory()
245        from pxr import UsdGeom
246        sphere = UsdGeom.Sphere.Define(s, Sdf.Path("/Sphere"))
247        radius = sphere.CreateRadiusAttr()
248        attrValueWriter = UsdUtils.SparseAttrValueWriter(radius,
249            defaultValue=1.0)
250
251        # Default value isn't authored into scene description since it matches
252        # the fallback value of radius.
253        self.assertFalse(radius.HasAuthoredValue())
254
255        attrValueWriter.SetTimeSample(10.0, 1.0)
256        attrValueWriter.SetTimeSample(10.0, 2.0)
257        attrValueWriter.SetTimeSample(10.0, 3.0)
258        attrValueWriter.SetTimeSample(20.0, 4.0)
259
260        self.assertEqual(radius.GetTimeSamples(), [1.0, 3.0, 4.0])
261
262    def test_SparseValueWriter(self):
263        s = Usd.Stage.CreateInMemory()
264        from pxr import UsdGeom
265        cylinder = UsdGeom.Cylinder.Define(s, Sdf.Path("/Cylinder"))
266        radius = cylinder.CreateRadiusAttr()
267        height = cylinder.CreateHeightAttr()
268
269        valueWriter = UsdUtils.SparseValueWriter()
270
271        valueWriter.SetAttribute(radius, 2.0, Usd.TimeCode.Default())
272        valueWriter.SetAttribute(height, 2.0, Usd.TimeCode.Default())
273
274        self.assertEqual(len(valueWriter.GetSparseAttrValueWriters()), 2)
275
276        # Default value isn't authored for the height attribute into scene
277        # description since it matches the fallback value of height.
278        self.assertFalse(height.HasAuthoredValue())
279
280        # Default value is authored for the radius attribute into scene
281        # description since it does not match the fallback value of radius,
282        # which is 1.0.
283        self.assertTrue(radius.HasAuthoredValue())
284
285        self.assertEqual(radius.Get(), 2.0)
286        # Calling SetAttribute again with time-Default will update the default
287        # value.
288        valueWriter.SetAttribute(radius, 5.0, Usd.TimeCode.Default())
289        self.assertEqual(radius.Get(), 5.0)
290
291        valueWriter.SetAttribute(radius, 10.0, 1.0)
292        valueWriter.SetAttribute(radius, 20.0, 2.0)
293        valueWriter.SetAttribute(radius, 20.0, 3.0)
294        valueWriter.SetAttribute(radius, 20.0, 4.0)
295
296        valueWriter.SetAttribute(height, 2.0, 1.0)
297        valueWriter.SetAttribute(height, 2.0, 2.0)
298        valueWriter.SetAttribute(height, 3.0, 3.0)
299        valueWriter.SetAttribute(height, 3.0, 4.0)
300
301        self.assertEqual(radius.GetTimeSamples(), [1.0, 2.0])
302        self.assertEqual(height.GetTimeSamples(), [2.0, 3.0])
303
304    def test_ErrorCases(self):
305        s = Usd.Stage.CreateInMemory()
306        scope = UsdGeom.Scope.Define(s, "/Scope")
307
308        attr1 = scope.GetPrim().CreateAttribute("attr1",
309                Sdf.ValueTypeNames.Float)
310        self.assertFalse(attr1.HasAuthoredValue())
311
312        attrValueWriter = UsdUtils.SparseAttrValueWriter(attr1)
313        # No default value was specified. So no authored value yet.
314        self.assertFalse(attr1.HasAuthoredValue())
315
316        attrValueWriter.SetTimeSample(10.0, time=10.0)
317        # Authoring an earlier time-sample than the previous one results in
318        # a coding error also.
319
320        # Calling SetTimeSample with time=default raises a coding error.
321        with self.assertRaises(Tf.ErrorException):
322            attrValueWriter.SetTimeSample(10.0, Usd.TimeCode.Default())
323
324        with self.assertRaises(Tf.ErrorException):
325            attrValueWriter.SetTimeSample(20.0, time=5.0)
326
327if __name__=="__main__":
328    unittest.main()
329