05.05.2022, 16:37 fxtd

Camel is a tool for VEX snippets and any other nodes with a custom interface.

It helps format the labels for new parameters if they were written in camel case. Camel also merges parameters into a vector (if they have x, y, etc. characters at the end of the name).

With this tool, you can format the node interface with two clicks: create spare parameters and launch Camel.

Parameters after creation
Parameters after Camel

You can download Camel here and bind it to the shelf, or use the next source code:

import hou
import re

def camel():
    skipTypes = [hou.parmTemplateType.FolderSet,
    hou.parmTemplateType.Folder,
    hou.parmTemplateType.Separator]
    camel = re.compile('^[a-z].*[A-Z]')
    xyzwString = 'xyzw'
    nameXYZW = re.compile('(.+)([{}])'.format(xyzwString))

    for node in hou.selectedNodes():
        templategroup = node.parmTemplateGroup()
        spareTuples = []
        houTuplesXYZW = {}

        for parm in node.spareParms():
            houTuple = parm.tuple()
            template = houTuple.parmTemplate()
            if nameXYZW.match(houTuple.name()) and len(houTuple) == 1 and \
            (template.type() == hou.parmTemplateType.Float or template.type() ==\
                hou.parmTemplateType.Int):
                key = nameXYZW.search(houTuple.name()).groups()[0]
                if key not in houTuplesXYZW:
                    houTuplesXYZW[key] = []
                    houTuplesXYZW[key].append(houTuple)
                elif template.type() == houTuplesXYZW[key][-1].parmTemplate().type() and \
                houTuple not in houTuplesXYZW[key]:
                    houTuplesXYZW[key].append(houTuple)

        for key in houTuplesXYZW.keys():
            houTuplesSolid = []
            charTuplesDict = {}

            for houTuple in houTuplesXYZW[key]:
                char = nameXYZW.search(houTuple.name()).groups()[1]
                charTuplesDict[char] = houTuple

            for char in xyzwString:
                if char in charTuplesDict:
                    houTuplesSolid.append(charTuplesDict[char])
                else:
                    break

            if len(houTuplesSolid) > 1:
                parmsValues = {}

                for houTuple in houTuplesSolid:
                    parm = tuple(houTuple)[0]
                    parmsValues[parm.name()] = parm.eval()

                newTemplate = houTuplesSolid[0].parmTemplate().clone()

                newName = nameXYZW.search(newTemplate.name()).groups()[0]
                newLabel = nameXYZW.search(newTemplate.label()).groups()[0]
                newTemplate.setName(newName)
                newTemplate.setLabel(newLabel)
                newTemplate.setNumComponents(len(houTuplesSolid))
                newTemplate.setNamingScheme(hou.parmNamingScheme.XYZW)

                firstTemplate = houTuplesSolid.pop(0).parmTemplate()
                templategroup.replace(firstTemplate.name(), newTemplate)
                for houTuple in houTuplesSolid:
                    templategroup.remove(houTuple.parmTemplate().name())

                for parmName in parmsValues.keys():
                    node.parm(parmName).set(parmsValues[parmName])

        node.setParmTemplateGroup(templategroup)

        for parm in node.spareParms():
            if parm.tuple() not in spareTuples:
                spareTuples.append(parm.tuple())

        for spareTuple in spareTuples:
            template = spareTuple.parmTemplate()
            if template.type() not in skipTypes:
                name = spareTuple.name()

                if camel.match(name):
                    splittedLabel = re.split(r'([A-Z]+)', name)
                    words = [splittedLabel.pop(0).title()]
                    words += [splittedLabel[n] + splittedLabel[n + 1] for n in \
                    range(0, len(splittedLabel), 2)]
                    template.setLabel(' '.join(words))
                    templategroup.replace(template.name(), template)
                    node.setParmTemplateGroup(templategroup)

20.02.2022, 19:41 fxtd

When using To NDC VOP node in a Volume VOP node, holes may appear in the volume:

This is because some threads are not calculating the VOP correctly. I think the reason of it is the To NDC node was created for shading context, and this may cause an error in the SOP context.

But To NDC node is a greate feature, because it doesn’t have any limits. We can use it for camera clipping, for example. If we do it with VDB, we need to think about the size and the depth of the masking VDB.

There is one method to check how it works. In bad areas z-component of NDC coordinates is the same like in source position P:

The first five records are the result of the erroneous working of the To NDC node

I tried doing it in inside a loop until z-components are the same (with fixed maximum number of steps), but it helped partically. Because sometimes they can be the same. I also tried doing it with SOP-loops, it didn’t help.

So, the only way to solve this problem is disabling multithreading on the Volume VOP node.


19.06.2020, 11:52 fxtd

It is recommended that you always specify attribute data types: i@class, f@pscale, s@name, and so on. There are a large number of possible errors associated with changing the data type of attributes. And initializing the data type is the first step to avoid these errors.


18.06.2020, 11:56 fxtd

If step voxels are visible when rendering the volume, then the necessary density field in the shader is missing.
This often happens when promoting the density attribute from volume shader core. Its name becomes density2 by default, and it must immediately be changed to density.


17.06.2020, 11:30 fxtd

Decreasing the Roughness parameter decreases the maximum amplitude that anti-aliased noise can generate.


15.06.2020, 23:31 fxtd

The pcfilter function sometimes may not understand the point.distance argument. Perhaps this is due to cases where there are no primitives.
Use the filter by the position of the point cloud.


15.06.2020, 11:25 fxtd

When using VEX Volume Procedural, you need to export all the necessary data for the render, including the velocity field.


14.06.2020, 20:38 fxtd

When converting a position to polar coordinates for presentation in the form of a map, you need to swap the Y and Z coordinates in the original position. Z axis should be multiplied by -1 for comfortable viewing.


14.06.2020, 13:04 fxtd

The two way switch turns off the entire branch, and it is not executed. “If” block does too. But all operators must be inside it for this.
When using the switch, all inputs are executed.


12.06.2020, 14:35 fxtd

Noise Name                            Min            Max

Perlin                                     0.55          1.37
Original Perlin                    -0.53          0.49
Sparse Convolution          -0.66           0.78
Alligator                                  0             0.53
Simplex                                -0.26          0.21
Zero centered perlin          -0.2            0.2
Anti-aliased                        -0.4            0.4


  • 1
  • 2