jupyter-widgets / pythreejs

A Jupyter - Three.js bridge
https://pythreejs.readthedocs.io
Other
936 stars 187 forks source link

Multiple morph targets #212

Closed jpanetta closed 5 years ago

jpanetta commented 5 years ago

The example notebook Animation.ipynb demonstrates how to create a single morph target and animate its influence. My attempts to add a second morph target have failed; an error is thrown when I try to add a second vertex position buffer:

morph.morphAttributes = {'position': [BufferAttribute(vertices)]} # works
morph.morphAttributes = {'position': [BufferAttribute(vertices), BufferAttribute(vertices)]} # fails

and it seems to be impossible to append to morph.morphAttributes['position'] after it's created.

I don't encounter any problems adding extra morph targets this way in plain threejs.

vidartf commented 5 years ago

and it seems to be impossible to append to morph.morphAttributes['position'] after it's created.

Well, this is a general issue with traitlets/widgets: Updating dicts or lists in-place will prevent the correct change events from triggering. The "correct" way is to copy the dict, modify the copy, and then assign the copy back. I.e. here, copy morphAttributes, modify the copy, reassign to morphAttributes.

My attempts to add a second morph target have failed; an error is thrown when I try to add a second vertex position buffer.

I'll look into it, but in general it would be instructive if you included the error in your report 👍

jpanetta commented 5 years ago

Sorry, the error output was rather long and seemed somewhat misleading so I figured it was easier for you to reproduce it in the example notebook by changing that line.

This is the error:
--------------------------------------------------------------------------
TraitError                                Traceback (most recent call last)
~/.local/lib/python3.6/site-packages/traitlets/traitlets.py in validate_elements(self, obj, value)
   2549                 if not isinstance(validate_with, Any):
-> 2550                     v = validate_with._validate(obj, v)
   2551             except TraitError:

~/.local/lib/python3.6/site-packages/traitlets/traitlets.py in _validate(self, obj, value)
    590         if hasattr(self, 'validate'):
--> 591             value = self.validate(obj, value)
    592         if obj._cross_validation_lock is False:

~/.local/lib/python3.6/site-packages/traitlets/traitlets.py in validate(self, obj, value)
   2241 
-> 2242         value = self.validate_elements(obj, value)
   2243 

~/.local/lib/python3.6/site-packages/traitlets/traitlets.py in validate_elements(self, obj, value)
   2438                 % (self.name, class_of(obj), len(self._traits), repr_type(value))
-> 2439             raise TraitError(e)
   2440 

TraitError: The 'None' trait of a BufferGeometry instance requires 1 elements, but a value of (BufferAttribute(array=array([[-0.0000000e+00,  1.0000000e+00,  0.0000000e+00],
       [-0.0000000e+00,  1.0000000e+00,  0.0000000e+00],
       [-0.0000000e+00,  1.0000000e+00,  0.0000000e+00],
       ...,
       [-1.1314261e-16, -1.0000000e+00, -4.6865205e-17],
       [-1.2011156e-16, -1.0000000e+00, -2.3891674e-17],
       [-1.2246469e-16, -1.0000000e+00, -2.9995195e-32]], dtype=float32)), BufferAttribute(array=array([[-0.0000000e+00,  1.0000000e+00,  0.0000000e+00],
       [-0.0000000e+00,  1.0000000e+00,  0.0000000e+00],
       [-0.0000000e+00,  1.0000000e+00,  0.0000000e+00],
       ...,
       [-1.1314261e-16, -1.0000000e+00, -4.6865205e-17],
       [-1.2011156e-16, -1.0000000e+00, -2.3891674e-17],
       [-1.2246469e-16, -1.0000000e+00, -2.9995195e-32]], dtype=float32)))  was specified.

During handling of the above exception, another exception occurred:

TraitError                                Traceback (most recent call last)
 in ()
     10         vertices2[i, 1] += -1
     11 morph.morphAttributes = {'position': [BufferAttribute(vertices)]} # works
---> 12 morph.morphAttributes = {'position': [BufferAttribute(vertices), BufferAttribute(vertices)]} # fails
     13 
     14 #morph.morphAttributes['position'].append(BufferAttribute(vertices))

~/.local/lib/python3.6/site-packages/traitlets/traitlets.py in __set__(self, obj, value)
    583             raise TraitError('The "%s" trait is read-only.' % self.name)
    584         else:
--> 585             self.set(obj, value)
    586 
    587     def _validate(self, obj, value):

~/.local/lib/python3.6/site-packages/traitlets/traitlets.py in set(self, obj, value)
    557 
    558     def set(self, obj, value):
--> 559         new_value = self._validate(obj, value)
    560         try:
    561             old_value = obj._trait_values[self.name]

~/.local/lib/python3.6/site-packages/traitlets/traitlets.py in _validate(self, obj, value)
    589             return value
    590         if hasattr(self, 'validate'):
--> 591             value = self.validate(obj, value)
    592         if obj._cross_validation_lock is False:
    593             value = self._cross_validate(obj, value)

~/.local/lib/python3.6/site-packages/traitlets/traitlets.py in validate(self, obj, value)
   2530         if value is None:
   2531             return value
-> 2532         value = self.validate_elements(obj, value)
   2533         return value
   2534 

~/.local/lib/python3.6/site-packages/traitlets/traitlets.py in validate_elements(self, obj, value)
   2550                     v = validate_with._validate(obj, v)
   2551             except TraitError:
-> 2552                 self.element_error(obj, v, validate_with)
   2553             else:
   2554                 validated[key] = v

~/.local/lib/python3.6/site-packages/traitlets/traitlets.py in element_error(self, obj, element, validator)
   2524         e = "Element of the '%s' trait of %s instance must be %s, but a value of %s was specified." \
   2525             % (self.name, class_of(obj), validator.info(), repr_type(element))
-> 2526         raise TraitError(e)
   2527 
   2528     def validate(self, obj, value):

TraitError: Element of the 'morphAttributes' trait of a BufferGeometry instance must be a tuple, but a value of [BufferAttribute(array=array([[-0.0000000e+00,  1.0000000e+00,  0.0000000e+00],
       [-0.0000000e+00,  1.0000000e+00,  0.0000000e+00],
       [-0.0000000e+00,  1.0000000e+00,  0.0000000e+00],
       ...,
       [-1.1314261e-16, -1.0000000e+00, -4.6865205e-17],
       [-1.2011156e-16, -1.0000000e+00, -2.3891674e-17],
       [-1.2246469e-16, -1.0000000e+00, -2.9995195e-32]], dtype=float32)), BufferAttribute(array=array([[-0.0000000e+00,  1.0000000e+00,  0.0000000e+00],
       [-0.0000000e+00,  1.0000000e+00,  0.0000000e+00],
       [-0.0000000e+00,  1.0000000e+00,  0.0000000e+00],
       ...,
       [-1.1314261e-16, -1.0000000e+00, -4.6865205e-17],
       [-1.2011156e-16, -1.0000000e+00, -2.3891674e-17],
       [-1.2246469e-16, -1.0000000e+00, -2.9995195e-32]], dtype=float32))]  was specified.
vidartf commented 5 years ago

Thanks for the report! Pushed a fix in #213.

PS: Note the edit I did you you log post to make it collapsible. A little trick 😉