Isotropix Forums

Exporting property values as double

Clarisse Scripting related topics

Exporting property values as double

Unread postby jboissinot » Tue Jan 29, 2019 10:48 pm

Hi there,

I've been dealing with some issues for exporting the values of items on a property as double.

Everything works well if we set the ResourceProperty object with TYPE_FLOAT_64 and its size to 3, and set the values with the set_double() method.
But the properties are not properly exported when using a size that's bigger than 3 like 4 or 16 for matrix transform values for instance.
We also tried with setting the type to TYPE_FLOAT_32 but it doesn't work either and actually returns the values as float instead of double.

As such, I was wondering if we were dealing with some kind of limitation here and if it'd be possible to do this.

Just putting this little code snippet to describe the question.
Code: Select all
import random


nbItems = 10

prop = createProperty('test')
prop.init(ix.api.ResourceProperty.TYPE_FLOAT_64, 4, nbItems)

for i in range(nbItems):
   for v in range(4):
      prop.set_double(i, random.uniform(), v)


Any help or thoughts on this would be appreciated.

Thanks,
Jeremy
jboissinot
 
Posts: 52
Joined: Tue Jan 29, 2019 10:36 pm

Re: Exporting property values as double

Unread postby bvaldes » Wed Jan 30, 2019 12:13 pm

Hi,

You should take a look to this post. I create a matrix property on this script: viewtopic.php?f=21&t=5100&p=17893#p17893

Tell me if this is not what you are looking for.

Regards
Benoit VALDES
Isotropix
Clarisse QA
User avatar
bvaldes
 
Posts: 384
Joined: Mon Sep 26, 2016 10:44 am

Re: Exporting property values as double

Unread postby anemoff » Wed Jan 30, 2019 12:32 pm

Just wanted to add the list of "standard" Alembic geometry property types that should be supported by applications, including Clarisse:

size 1:
- int8, uint8
- int16, uint16
- int32, uint32
- int64, uint64
- float16
- float32
- float64

size 2
- int16 interpreted as vec2
- int 32 interpreted as vec2
- float32 interpreted as vec2
- float64 interpreted as vec2

size 3
- uint8 interpreted as color3
- int16 interpreted as vec3
- int32 interpreted as vec3
- float16 interpreted as color3
- float32 interpreted as vec3
- float64 interpreted as vec3

size 4
- uint8 interpreted as color4
- int16 interpreted as box2 (2 x 2D points)
- int32 interpreted as box2
- float16 interpreted as color4
- float32 interpreted as quaternion
- float64 interpreted as quaternion

size 6
- int16 interpreted as box3 (2 x 3D points)
- int32 interpreted as box3
- float32 interpreted as box3
- float64 interpreted as box3

size 9
- float32 interpreted as matrix3x3
- float64 interpreted as matrix3x3

size 16
- float32 interpreted as matrix4x4
- float64 interpreted as matrix4x4

Other properties with non-standard type-size combinations are supported on import by Clarisse but might not be supported by other applications (Maya, Houdini, ...) because they are not standard Alembic geometry properties. They are just regular properties. For example a property of type float32 with size 5 is not an Alembic geometry property.

Also, can you send us the details of your "createProperty" function? Maybe there's an issue in there.

Cheers.
Anthony Nemoff
Isotropix
R&D Engineer
User avatar
anemoff
 
Posts: 192
Joined: Wed Jan 13, 2016 10:10 am

Re: Exporting property values as double

Unread postby jboissinot » Wed Jan 30, 2019 11:38 pm

Hi,

Benoit,

We did use the matrix property method you're referring too. The only thing that I was doing differently though was to store all items of the matrix in a list and parse that list for setting the values in the property. Even though the values seemed to be correct when printing both while testing it, it appears that some values were wrong or undefined on the end when being loaded in other applications. Setting the values in a property directly while parsing the matrix seems to have fixed the issue as all the values come correctly now. I guess it might be a restriction to not store the matrix items in a list and have to be set with the matrix object but not quite sure about this and you'd may confirm this. But following what Anthony sent, I think it was just a matter of setting the values as a matrix4x4 and not a list of size 16.

Despite that, we still have the issue for exporting the values as double as they come completely wrong in other applications when using the set_double() function. We found out in the scripting documentation that the vec3 and matrix4x4 objects can support double and float values, and we were wondering if we'd need to define this in the object to be able to set the proper data type.


Anthony,

Thanks for sharing this list of property types, this is definitely relevant and helpful information.
We were actually setting the values of the property with a custom list of size 4 which was wrong.
So we tried the quaternion method by storing the rotation angle value and the rotation axis as a vec3 in a quat object as you can see in the code below.

Code: Select all
rotate = ix.api.GMathVec3d()
matrix.compute_euler_angles(rotate)

xRot = rotate[0]
yRot = rotate[1]
zRot = rotate[2]

xRotAxis = ix.api.GMathVec3d(1,0,0)
yRotAxis = ix.api.GMathVec3d(0,1,0)
zRotAxis = ix.api.GMathVec3d(0,0,1)

xRotQuat = ix.api.GMathQuat()
xRotQuat.set_rotation(xRot, xRotAxis)

yRotQuat = ix.api.GMathQuat()
yRotQuat.set_rotation(yRot, yRotAxis)

zRotQuat = ix.api.GMathQuat()
zRotQuat.set_rotation(zRot, zRotAxis)

for v in range(4):
        instanceRotateX.set_double(i, xRotQuat[v], v)
for v in range(4):
        instanceRotateY.set_double(i, yRotQuat[v], v)
for v in range(4):
        instanceRotateZ.set_double(i, zRotQuat[v], v)


We're getting the following error when running the script:
AttributeError: 'module' object has no attribute 'GMathQuat'

We're not actually quite sure on how to create a quaternion object, this is just how we did it based on the documentation.

Thanks for your help,
Jeremy
jboissinot
 
Posts: 52
Joined: Tue Jan 29, 2019 10:36 pm

Re: Exporting property values as double

Unread postby anemoff » Fri Feb 01, 2019 6:42 pm

Actually, GMathQuat isn't available in python, hence your error.
This is a bug and we have added it to our bug database with the ID #9247.
We will add GMathQuat to the python API.

You can use a GMathVec4 just for storing 4 double values. But you won't have the quaternion API, it'll just serve as an array of 4 doubles.
Anthony Nemoff
Isotropix
R&D Engineer
User avatar
anemoff
 
Posts: 192
Joined: Wed Jan 13, 2016 10:10 am

Re: Exporting property values as double

Unread postby anemoff » Mon Feb 11, 2019 4:18 pm

Hi!

Here's a script that uses the IOHelpers API to create and edit the point properties instead of using directly the ResourceProperty API.
The IOHelpers API is mainly dedicated to edit ParticleContainer objects, so I hope this is your case.
Please note that currently the Property Editor isn't notified when a new property is added via IOHelpers. Close it and open a new one to show all properties.

For the sake of testing, I'm creating matrices with random values, but you just have to replace that with your real matrices.
I have attached the script and a project that uses it.

I hope this answers your needs. Let me know if you have questions.
We will also investigate the set_double issue.

python code

import random

INVALID_INDEX = -1 + 2**32

ENABLE_DEBUG_LOGS = False

def log_debug(msg):
if ENABLE_DEBUG_LOGS:
ix.log_info('[DEBUG] %r' % msg)

# -------------------------------------------------------------------
# Helpers for ResourceProperty.

value_types = {
0 : 'int8',
1 : 'uint8',
2 : 'int16',
3 : 'uint16',
4 : 'int32',
5 : 'uint32',
6 : 'int64',
7 : 'uint64',
8 : 'float16',
9 : 'float32',
10 : 'float64',
11 : 'char',
12 : 'wchar',
}

def get_type_size(value_type):
"""
Get the property type size in bytes. Example: float32 -> 4 bytes.
"""
return ix.api.ResourceProperty.get_type_size(value_type)

def get_type_name(value_type, with_size = False):
"""
Get the property type as name string.
"""
if value_type in value_types:
if with_size:
return '%s (%d bytes)' % (value_types[value_type], get_type_size(value_type))
else:
return '%s' % value_types[value_type]
else:
return'unknown'

def get_values_as(resource, item_index, value_type):
"""
Get the resources values of the item at the given index.
If the requested type doesn't match with the actual property type an empty value list is returned,
"""

if value_type == ix.api.ResourceProperty.TYPE_CHAR:
return resource.get_string(item_index)

if value_type == ix.api.ResourceProperty.TYPE_INT_8 or value_type == ix.api.ResourceProperty.TYPE_UINT_8:
return resource.get_byte(item_index)

if value_type == ix.api.ResourceProperty.TYPE_INT_16 or value_type == ix.api.ResourceProperty.TYPE_UINT_16:
return resource.get_short(item_index)

if value_type == ix.api.ResourceProperty.TYPE_INT_32 or value_type == ix.api.ResourceProperty.TYPE_UINT_32:
return resource.get_int(item_index)

if value_type == ix.api.ResourceProperty.TYPE_INT_64 or value_type == ix.api.ResourceProperty.TYPE_UINT_64:
return resource.get_long(item_index)

elif value_type == ix.api.ResourceProperty.TYPE_FLOAT_32:
return resource.get_float(item_index)

elif value_type == ix.api.ResourceProperty.TYPE_FLOAT_64:
return resource.get_double(item_index)

ix.log_warning('get_values_as: unsupported type "%s"' % get_type_name(value_type))
return []

# -------------------------------------------------------------------
# Functions to create dummy matrix data and convert it to string.

def create_dummy_m44d(random_values = False, transpose = True):
"""
Create a GMathMatrix4x4d with values for the sake of testing.
"""
if random_values:
# matrix with random values
m44d = ix.api.GMathMatrix4x4d()
for i in range(4):
for j in range(4):
m44d.set_item(i, j, random.random())
else:
# identity matrix
m44d = ix.api.GMathMatrix4x4d(True)

# to be in Alembic format the matrix must be transposed
if transpose:
m44d.transpose()

return m44d

def m44d_to_string(m44d, separator = ' '):
"""
Get the GMathMatrix4x4d flattened values as a string separated with the separator.
"""
s = ''
for i in range(4):
for j in range(4):
s += '%f' % m44d.get_item(i, j)
if j < 3: s += separator
if i < 3: s += separator
return s

# -------------------------------------------------------------------

def get_point_property(particle_object, prop_name):
"""
Get a GeometryPointProperty from a GeometryParticle object.
"""

prop_collection = particle_object.get_module().get_properties()
if not prop_collection:
ix.log_warning('There are no properties.')
return None

prop_index = prop_collection.get_property_index(prop_name)
if prop_index == INVALID_INDEX:
ix.log_warning('Property "' + prop_name + '" not found.')
return None

prop = prop_collection.get_property(prop_index)
if not prop:
ix.log_warning('Failed to retrieve property "' + prop_name + '".')
return None

return prop

# -------------------------------------------------------------------

def get_point_property_indices(particle_object, prop_name):
"""
Get the GeometryPointProperty indices.
Returns None if the property isn't found or isn't indexed.
"""

prop = get_point_property(particle_object, prop_name)
if not prop:
return None

if not prop.has_indices():
return None

return prop.get_indices()

# -------------------------------------------------------------------

def print_point_property_indices(particle_object, prop_name):
"""
Get the value indices of the GeometryPointProperty.
"""

indices = get_point_property_indices(particle_object, prop_name)
if indices:
s = []
for i in indices:
s.append(i)
print 'Value indices for %s: index count = %d, indices = %r' % (prop_name, indices.get_count(), s)

# -------------------------------------------------------------------

def create_point_property(particle_container_object, prop_name, value_type, dimension):
"""
Create a GeometryPointProperty in a GeometryParticleContainer with no values.
If the property already exists it is overwritten.

Known bug in 3.6 SP8: the Property Editor doesn't refresh after a property has been created by IOHelpers.

Parameters
----------
particle_container_object:
The GeometryParticleContainer object.
prop_name:
Property name.
value_type:
Property value type (see ResourceProperty.Type).
dimension:
Property dimension: number of data items per value.
Examples:
- 1 vector3 value has 3 data items -> dimension = 3
- 1 matrix44 value has 16 data items -> dimension = 16

Returns
-------
Boolean:
True if succeeded, False otherwise.
"""

print 'Creating property "%s.%s" ...' % (particle_container_object.get_name(), prop_name)
return ix.api.IOHelpers.create_particles_property(particle_container_object, prop_name, value_type, dimension, '')

# -------------------------------------------------------------------

def set_point_property_values(particle_container_object, prop_name, values):
"""
Set the values of a GeometryPointProperty in a GeometryParticleContainer.

This implementation might be limited if the values array is too big.
It could be possible to rework to add a parameter containing a list of point
indices along with the associated values, so that the values can be set by chunks.

Parameters
----------
particle_container_object:
The GeometryParticleContainer object.
prop_name:
Property name.
values:
Python string array containg 1 string value per point.
Each string must contain as many values (separated by spaces) as the dimension of the property.
If there are too many values the excess values are ignored.
If there are not enough values, some points won't have values.
Example:
- to set the values of 2 x vec2f to (1.0, 2.0) and (3.0 4.0), the python string array is ["1.0 2.0", "3.0 4.0"].

Returns
-------
Boolean:
True if all values were set, False if at least one value failed to be set.

"""

print 'Setting values in property "%s.%s" ...' % (particle_container_object.get_name(), prop_name)

point_count = int(particle_container_object.get_module().get_point_count())
values_used = min(point_count, len(values))
if len(values) != point_count:
ix.log_warning('Value count (%d) and point count (%d) differ: only %d values will be used.' % (point_count, len(values), values_used))
return

# NOTE: this function would require some reworking to use indexed values in order to reduce the number of stored values, to share
# values between points. For example you can have N values, and assign those N values to M points, where M = point_count and N <= M.
# - point 0 -> assign value at index 0
# - point 1 -> assign value at index 0
# - point 2 -> assign value at index 2
# ...
# - point M-1 -> assign value at index 1


# assign each value to each point
all_ok = False
for i in range(values_used):
# create a new value index for the new value
new_indices = ix.api.ULongSet()
new_indices.add(i)
ok = ix.api.IOHelpers.edit_particles_property(particle_container_object, prop_name, new_indices, ix.api.IOHelpers.EDIT_PROPERTY_MODE_SET, values[i])
if not ok:
ix.log_warning('Failed to set value for point %d.' % i)
all_ok = all_ok and ok

return all_ok

# -------------------------------------------------------------------

def print_property_values(particle_container_object, prop_name, value_type):
"""
Print the values of a GeometryPointProperty in a GeometryParticleContainer.
"""

print 'Printing property "%s.%s" ...' % (particle_container_object.get_name(), prop_name)

module = particle_container_object.get_module()
point_count = int(module.get_point_count())
log_debug('point count = %d' % point_count)

# get the property collection
prop_collection = module.get_properties()
if not prop_collection:
ix.log_warning('No properties.')
return

# get the property index
prop_index = prop_collection.get_property_index(prop_name)
if prop_index == INVALID_INDEX:
ix.log_warning('Property "' + prop_name + '" not found.')
return

# get the property
prop = prop_collection.get_property(prop_index)
if not prop:
ix.log_warning('Failed to get property "%s" at index %d.' % (prop_name, prop_index))
return

value_type = prop.get_value_type()

# debug stuff
value_count = prop.get_value_count() # number of property values
value_extent = prop.get_value_extent() # number of value item per per property value (e.g. vec2 has extent = 2)
index_count = prop.get_index_count()
time_sampling = prop.get_time_sampling()
sample_count = time_sampling.get_sample_count()
log_debug('value_type = %d (%s)' % (value_type, get_type_name(value_type)))
log_debug('value_count = %d' % value_count) # number of values: 2 x vec3f -> 2
log_debug('value_extent = %d' % value_extent) # number of value "items" per value: vec3f -> 3
log_debug('index_count = %d' % index_count) # number of indices: usually same as number of points
log_debug('sample_count = %d' % sample_count) # number of samples per value
log_debug('has_indices = %r' % prop.has_indices())

# get the ResourceProperty for the 1st sample (0)
resource = prop.get_values_property(0)

# debug stuff
log_debug('resource.value_size = %r' % resource.get_value_size()) # size of 1 value item: vec3f -> float32 = 4 bytes
log_debug('resource.item_count = %r' % resource.get_item_count()) # number of values (== prop.value_count)
log_debug('resource.value_count = %r' % resource.get_value_count()) # total number of value items: 2 x vec3f -> 2 x 3 = 6
log_debug('resource.item_value_count = %r' % resource.get_item_value_count(0)) # number of items per value: vec3f -> 3

# iterate over the points
for item_index in range(resource.get_item_count()):
cur_values = get_values_as(resource, item_index, value_type)

log_debug('len(cur_values) = %r' % len(cur_values))
log_debug('cur_values = %r' % cur_values)

if len(cur_values) == 0:
continue

cur_extent = resource.get_item_value_count(item_index)
log_debug('cur_extent = %d' % cur_extent)

log = 'value %d = ' % item_index
if value_type == ix.api.ResourceProperty.TYPE_CHAR:
log += cur_values[:cur_extent]
else:
for i in range(cur_extent):
log += '%r ' % cur_values[i]
print log


# -------------------------------------------------------------------
# Run it !

# get the particle container and its point count
container = ix.get_item("project://scene/context/container")
point_count = int(container.get_module().get_point_count())

# ----- create a matrix44d property (dim 16) -----

# create as many matrices as points in the particle container, and put the values in a string array
m44d_values = []
for i in range(point_count):
m44d = create_dummy_m44d(True)
m44d_values.append(m44d_to_string(m44d))

prop_name = 'm44_float64'
create_point_property(container, prop_name, ix.api.ResourceProperty.TYPE_FLOAT_64, 16)
set_point_property_values(container, prop_name, m44d_values)
print_property_values(container, prop_name, ix.api.ResourceProperty.TYPE_FLOAT_64)

# ----- create an int32 property (dim 1) -----
int32_values = []
for i in range(point_count):
int32_values.append(str(i))

prop_name = 'int32'
create_point_property(container, prop_name, ix.api.ResourceProperty.TYPE_INT_32, 1)
set_point_property_values(container, prop_name, int32_values)
print_property_values(container, prop_name, ix.api.ResourceProperty.TYPE_INT_32)

# ----- create a string property (dim 1) -----
text_values = []
for i in range(point_count):
text_values.append('text_%d' % i)

prop_name = 'text'
create_point_property(container, prop_name, ix.api.ResourceProperty.TYPE_CHAR, 1)
set_point_property_values(container, prop_name, text_values)
print_property_values(container, prop_name, ix.api.ResourceProperty.TYPE_CHAR)
Attachments
edit_container_properties.py
(13.68 KiB) Downloaded 53 times
export_matrix_property.project
(36.88 KiB) Downloaded 53 times
Anthony Nemoff
Isotropix
R&D Engineer
User avatar
anemoff
 
Posts: 192
Joined: Wed Jan 13, 2016 10:10 am

Re: Exporting property values as double

Unread postby jboissinot » Tue Mar 26, 2019 11:49 pm

Hi,

I just wanted to follow up on this as it is still something that we aim to achieve and had some questions about it:

- Would it be possible to store 16 values in a property of size 1? like we can do for string type properties with the separator method that allows us set multiple values into one single property.

- Is the set_double method with CoreBasicArray implemented in Python API? If so, how could we convert a matrix4x4 to a CoreBasicArray?

I tried this as a quick example with a custom list, but the idea would be the same in parsing the items of a matrix4x4:

Code: Select all
matrixArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
array = ix.api.CoreBasicArrayd()
for i in range(len(matrixArray)):
    array.set_item(i, matrixArray[i])



Thanks,
Jeremy
jboissinot
 
Posts: 52
Joined: Tue Jan 29, 2019 10:36 pm

Re: Exporting property values as double

Unread postby anemoff » Wed Mar 27, 2019 6:19 pm

Hi,

jboissinot wrote:- Would it be possible to store 16 values in a property of size 1? like we can do for string type properties with the separator method that allows us set multiple values into one single property.

Yes, using a string property and any character separator of your choice except '.' (space or ';' for example), like we discussed previously.
However, you can have precision loss when converting float or double values to string.

Here is an example that converts a 4x4 matrix to a single string. You can then write the resulting string value into a string property of your Particle Container.

python code

def m44_to_string(m44, separator = ' '):
"""
Convert a GMathMatrix4x4 (float or double) to a string containing the flattened values in row-major order, separated with the separator.
"""

s = ''
for row in range(4):
for col in range(4):
s += '%r' % m44.get_item(row, col)
if col < 3: s += separator
if row < 3: s += separator
return s

# GMathMatrix4x4d to string
m44d = ix.api.GMathMatrix4x4d(True)
print 'm44d:\n{}'.format(m44d)
m44d_str = m44_to_string(m44d)
print 'm44d_str: {}\n'.format(m44d_str)

# GMathMatrix4x4f to string
m44f = ix.api.GMathMatrix4x4f(True)
print 'm44f:\n{}'.format(m44f)
m44f_str = m44_to_string(m44f)
print 'm44f_str: {}\n'.format(m44f_str)

Output:
Code: Select all
m44d:
1 0.0 0.0 0.0
0.0 1 0.0 0.0
0.0 0.0 1 0.0
0.0 0.0 0.0 1

m44d_str: 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0

m44f:
1.000000000000000 0.0 0.0 0.0
0.0 1.000000000000000 0.0 0.0
0.0 0.0 1.000000000000000 0.0
0.0 0.0 0.0 1.000000000000000

m44f_str: 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0


jboissinot wrote:- Is the set_double method with CoreBasicArray implemented in Python API? If so, how could we convert a matrix4x4 to a CoreBasicArray?

Actually, CoreBasicArrays are read-only arrays. You want to use CoreArray or CoreVector for read-write.
In Python, the names are a bit different depending on the contained typed: DoubleArray, FloatArray, DoubleVector, FloatVector, etc.
See here for more details: https://www.clarissewiki.com/4.0/sdk/py ... d_cpp.html

There's no built-in method to convert a GMathMatrix4x4 to an array, neither a method to set a list of (double) values into an CoreArray (in Python).
However, it's easy to do:

python code

def m44_to_array_double(m44):
"""
Convert a GMathMatrix4x4 (float or double) to a flattened row-major order array of doubles.
"""

array = ix.api.DoubleArray(16)
for row in range(4):
for col in range(4):
array[row + col * 4] = m44.get_item(row, col)
return array

def m44_to_array_float(m44):
"""
Convert a GMathMatrix4x4 (float or double) to a flattened row-major order array of floats.
"""

array = ix.api.FloatArray(16)
for row in range(4):
for col in range(4):
array[row + col * 4] = m44.get_item(row, col)
return array


# GMathMatrix4x4d
m44d = ix.api.GMathMatrix4x4d(True)
print 'm44d:\n{}'.format(m44d)

# convert to a DoubleArray
m44d_array = m44_to_array_double(m44d)
print 'm44d_array:'
for i in range(m44d_array.get_count()):
print '[{}] = {}'.format(i, m44d_array[i])


print ''

# convert to a FloatArray
m44f_array = m44_to_array_float(m44d)
print 'm44f_array:'
for i in range(m44f_array.get_count()):
print '[{}] = {}'.format(i, m44f_array[i])


Output:
Code: Select all
m44d:
1 0.0 0.0 0.0
0.0 1 0.0 0.0
0.0 0.0 1 0.0
0.0 0.0 0.0 1

m44d_array:
[0] = 1.0
[1] = 0.0
[2] = 0.0
[3] = 0.0
[4] = 0.0
[5] = 1.0
[6] = 0.0
[7] = 0.0
[8] = 0.0
[9] = 0.0
[10] = 1.0
[11] = 0.0
[12] = 0.0
[13] = 0.0
[14] = 0.0
[15] = 1.0

m44f_array:
[0] = 1.0
[1] = 0.0
[2] = 0.0
[3] = 0.0
[4] = 0.0
[5] = 1.0
[6] = 0.0
[7] = 0.0
[8] = 0.0
[9] = 0.0
[10] = 1.0
[11] = 0.0
[12] = 0.0
[13] = 0.0
[14] = 0.0
[15] = 1.0


Does this answer your questions?
Let me know if you need more help.

Cheers,
Anthony Nemoff
Isotropix
R&D Engineer
User avatar
anemoff
 
Posts: 192
Joined: Wed Jan 13, 2016 10:10 am

Re: Exporting property values as double

Unread postby jboissinot » Thu Apr 04, 2019 12:14 am

Hi,

Yes I did use the string method with separators and the IOHelpers API which works fine for an export to Houdini but doesn't for Katana as it requires double values.

The goal for us is to find a way to put in place a common export that will work for both applications hopefully.

I used the same method you sent for converting a matrix to an array. Thanks for the info regarding the CoreArray object.
If I set the matrix values in a DoubleArray and store them with the set_double, it works well as the values do come as double in Katana, while it doesn't in Houdini as only the "number of points" values come in and are not stored per point.

What I noticed actually when I check the point cloud data from the property editor is that the count value of the matrix property results in the number of points multiplied by 16. For example, if we have 10 points, the count value turns to be 160 even though I do set the arrays of values per point index.

Code: Select all
matrixProp.init(ix.api.ResourceProperty.TYPE_FLOAT_64, 1, nbPoints * 16) # doesn't store all values if set with nbPoints only
...
for i in range(nbPoints):
    array = ix.api.DoubleArray(16)
    for x in range(4):
        for y in range(4):
            array[x + y * 4] = matrix.get_item(x, y) 
    matrixProp.set_double(i, array)


As such, I was wondering if it'd be possible to store 16 double values in a property of size 1 per point index, like we can do for strings for instance.
The problem with using the IOHelpers API method is that, like you said, we can loss double precision, and the values will automatically be stored as float if they are set in a FLOAT type property. I mean, would there be a way to store them as double with the IOHelpers API method?

Thanks,
Jeremy
jboissinot
 
Posts: 52
Joined: Tue Jan 29, 2019 10:36 pm

Re: Exporting property values as double

Unread postby anemoff » Wed Apr 10, 2019 5:45 pm

Hi,

Sorry for the late response.

From our previous tests, it seems that Katana doesn't support matrix 4x4 as double (see our previous emails).
We don't have Katana to confirm that, but we had successfully imported in Houdini a m44d exported by Clarisse.

As such, I was wondering if it'd be possible to store 16 double values in a property of size 1 per point index, like we can do for strings for instance.

No. For types other than string, the only way to store multiple values is in an array.

I mean, would there be a way to store them as double with the IOHelpers API method?

Yes, you need to create the property with the type TYPE_FLOAT_64 if you want doubles.
However, you still have the issue of potential precision loss from the double to string conversion.

I need some more time to find a suitable workflow for what you need, sorry.
I'll keep you posted ASAP.
Anthony Nemoff
Isotropix
R&D Engineer
User avatar
anemoff
 
Posts: 192
Joined: Wed Jan 13, 2016 10:10 am

Next

Return to Scripting