Monthly Archives: January 2015

Point Cloud in Houdini

Point cloud is an amazing feature in Houdini.
Below is a very basic example showing simplest use of point cloud using VEXpression.

Setup

point_clouds_101

VEX Code in PointWrangle SOP


float maxradius = 5;
vector nb_color;
float dist;

int handle = pcopen(@OpInput2, "P", @P, maxradius, 10);

while(pciterate(handle))
{
    pcimport(handle, "Cd", nb_color);
    pcimport(handle, "point.distance", dist);
    @Cd = lerp(@Cd, nb_color, dist/maxradius);
}

 

Alright, so let’s walk through the code.
First we declare all required variables.

float maxradius = 5;
vector nb_color;
float dist;

Then we use pcopen to “open” a point cloud.
Basically we are asking to retrieve 10 points from the geometry connected in 2nd input (@OpInput2) within maximum given radius near the position (@P) of currently being processed point (of geometry in 1st input).

int handle = pcopen(@OpInput2, "P", @P, maxradius, 10);

Now, we “iterate” through all the retrieved points.
This is similar to pseudo code : for(int i = 0; i < numpointsincloud; i++).
But Houdini provides pciterate which will iterate through all the points and will return false when all in the cloud are processed.

while(pciterate(handle))

Remember that VEX runs per-point (or per-prim…), so we are not iterating through the points of our main geometry but through the points from cloud around that point, lets call it main point.
Now we import whichever parameter we want from this cloud into local variables using pcimport.
In our case, we want the color (Cd) of the points and their distance from main point.

pcimport(handle, "Cd", nb_color);
pcimport(handle, "point.distance", dist);

And finally, we use imported data to alter attribute(s) of main point.

@Cd = lerp(@Cd, nb_color, dist/maxradius);

 

Result

point_clouds_result

Advertisements

HOUtilities

Introducing HOUtilities, collection of small to large utilities and tools written in Python/PySide, to make Houdini artists/TDs lives easier.
Source code coming soon after adding all features for version 1.0 and proper testing.

Current utilities include –

Frequent OPs
Quick access to most frequently used OPs.
This will allow users to design their own prefs. with user defined frequent OPs, colors per OP category, context sensitive OPs, as well as auto-naming etc…

FrequentOPs

HDA Manager
HDA Manager is designed to make dealing with lots of HDAs easier.
Feature will include ability to favourite HDAs to keep them at top, saving individual as well as all unlocked HDAs and quickly fetching various information about any HDA.

HDAManager

Miscellaneous Utilities
As it suggests, these are small but sometimes handy set of utilities.
First one is to add a switch sop to selected sop and expose switch’s input parm to parent Geo or HDA as a toggle – all in a click.

switch_001 switch_002

Multiblend shader with Snow

Below are few screenshots of a shader I am working on.

It blends two sets of texture maps (Diffuse, Normal, Specular) based on vertex alpha and diffuse alpha channel. And applies snow color, normal map & specular for pixels facing upwards.


multiblend_snow_001

multiblend_snow_002

Add a switch to selected Houdini node

Here is a quick way to add a switch to currently selected Houdini Node.
For further improvements it would be great to have switch input exposed to parent HDA’s interface.
Also an option to have auto-Null input to switch sop.
i.e. “Switch to nothing” mode.


def addSwitchForDebug(self, parentOp = ""):
	'''
	Add switch op to bypass selected node and expose switch input to the parent.
	'''

	currentSel = hou.selectedNodes()
	if len(currentSel) == 1:
		current = currentSel[0]
		opName = "switch"
		parentNode = hou.node(current.path()).parent()

		# Get inputs and outputs
		outNodes = current.outputs()
		inNodes = current.inputs()

		#Create switch
		newNode = current.createOutputNode(opName)
		newNode.setName(opName, True)
		newNode.setColor(Color.Default)

		# Set correct inputs to switch node
		if len(inNodes) > 0:
			newNode.setFirstInput(inNodes[0])
			newNode.setNextInput(current)

		# Insert switch between current and its immediate output node
		if len(outNodes) > 0:
			currentOut = outNodes[0]
			currentOut.setFirstInput(newNode)

		newNode.moveToGoodPosition()