Spring 2021 Reflection: Automatic Node Generation

In the Visualizing Cities project this semester, one of my first tasks in Houdini was to modify the Python code that processed our JSON data. The original node resulted in many unused fields being present in the data spreadsheet, and I modified the processing method to first iterate through the data and record a list of the fields that were used. The rest of the processing code could use this list to determine whether each field in a template file (meta.json) was necessary. Regarding efficiency, iterating through the data file twice is only a linear increase in time complexity, but since it would be best if we did not iterate through the data file twice, future work might consider creating the necessary fields on the first pass through the data file.

Another important task involved finding a way to drop objects into the Houdini scene based on the class of a data point – for instance, a data point with a class of “Rocks” would require a rock HDA to be placed into the scene. Since the object HDAs were being developed in parallel to my work, I began by utilizing basic geometries, such as cubes and spheres, and placed these into the scene based on class. Xinyue Qian continued development on this task and successfully created a network that placed different geometries based on the class attribute. When the object HDAs are fully developed, this work should be useful in allowing us to place different objects in their correct locations.

My much more complex task this semester was related to the data filtering task above – after successfully switching between types of geometries based on the “class” attribute, I still needed to determine the correct point, or location where the geometry should be placed. Since many objects are divided into multiple parts in the data, (building facades, roof parts etc.) I needed to find a central point where the entire object HDA could be dropped. For this task, I utilized automatic node generation using Python. My first attempt at the network involved creating groups by class, then creating groups by instance ID (essentially a key value that designates which traced building parts are part of the same object) within each class group, and finally using VEX code to find the “centroid” of each instance group. Most of the network was automatically created using Python. An issue with this attempt was that some data points of different classes still shared instance IDs – for example, data points in the “House part” class would share an instance ID with a data point in the “Roof” class, but the initial separation by class group resulted in these points being considered separately. To address this problem, I created a new network that does not break objects into class groups – the network simply removes all data points that are in a 2D class (i.e. data points for objects like trees that should not have multiple parts or instance IDs), creates instance groups from the remaining points, and finds the centroid of each instance group. There is a small remaining issue with the centroid point being added to the data hundreds of times instead of only once, but it is likely that a Fuse node should be able to merge these identical points into one. This work will be helpful in taking object HDAs and placing them in the correct locations in our scenes. Additionally, because many Houdini tasks involve steps that iterate over the data, the general process of automatically generating nodes via Python code will hopefully be utilized in a broader range of tasks throughout the project.

Overall, my work on the project this semester exposed me to various applications of different coding languages like Python and VEX to problems in 3D modeling, and I hope that my Python development and Houdini sub-networks will be beneficial to future project tasks.