I'm starting to get back into developing custom digital assets to fill some gaps in Houdini's out-of-box (and Labs) operator set. Many of these will be assets built from other nodes, particularly in SOPs, and I'll be creating and manipulating geometry attributes and groups internally within the asset. Whenever this happens, there's a risk that attribute and group names collide with existing names on the input geometry, potentially leading to undesirable behaviour within the asset. I've been wrestling with how to handle this in a way that is robust and transparent to the user, and thought I'd share my thinking here for comment. The options I've come up with so far are:
Ignore the problem
Use whatever attribute / group names make sense to me and overwrite any identically-named attributes / groups that the user has unwittingly supplied as input geometry. Not a particularly forgiving experience for the user, and could easily lead to confusion when things don't work as expected.
Obfuscate the internal names
I've lifted the lid on some Labs assets and noticed a tendency (but not quite frequent enough to be considered a rule) to prefix internal names with single or double underscores, a bit like how python 'hides' class internals. If this (or something similar) was an established practice that Houdini users knew and adhered to, this would probably work quite well and I wouldn't need to think any more on the problem. But it isn't, as far as I can tell (please correct if you know otherwise; the Labs assets may be trying to establish a precedent here). And there remains the possibility that a user who is unaware of such a convention or perhaps imports geometry from another package with conflicting attribute/group names that unknowingly interfere with the asset internals.
Raise an error / warning
With prefixed or otherwise obfuscated internal names for attributes/groups, for the rare occasions that a naming conflict does arise, the asset could simply raise an error or warning about a name collision. That puts the onus on the user to fix it by renaming one or more attribute/group names, which is better than silently ignoring the collision, but still feels like a suboptimal experience for a user in that position.
Procedurally rename internal names upon collision
This is the approach I've settled on thus far, and seems the most Houdini-like and acceptable from a user perspective, and introduces only moderate inconvenience to an asset developer. It works by branching the asset input geometry into a custom Python SOP, into which I list all the internal attribute and group names I want to use. The Python code then checks each name against the incoming geometry, and appends/increments the name by one if there is a collision - just like node names do when you copy-paste them or try to create a node name conflict - until it finds a unique name. The Python code then creates a dictionary attribute at the global geometry (detail) level with desired names as the keys (e.g. 'uv') and resulting names after collision-testing as the values (e.g. 'uv1').
Why store the mapping in an attribute? Well, the deconflicted names need to be referenced in string parameters of other nodes, and potentially in VEX or other Python code elsewhere in the asset, and there are established ways of doing this that don't require custom functions to be written. And the detail attribute itself does not propagate any further through the network, since it terminates that branch and is only indirectly referenced by the output geometry pipeline.
And so instead of referencing the original attribute / group names directly in node parameters (and any VEX/Python code within the asset), I instead retrieve the corresponding dictionary value from the detail attribute in the other branch, using the original name as key. Fully procedural, and guaranteed not to result in name collisions at runtime, regardless of whatever attribute or group names exist on the input geometry. It does, however, necessitate Python's slighty more verbose channel referencing syntax, because I haven't yet found a way to get Hscript / Expressions to work with dictionary attributes (again, would welcome any advice to the contrary).
With this approach, an asset developer can focus on getting the asset working right, using whatever internal attribute and group names make sense, and append these to the list of names in the custom Python SOP as they go. As development nears completion, one needs to then convert any hard-coded attribute/group names into references to the detail dictionary, but that's fairly trivial and could well be automated with a script (which I haven't bothered with owing to the relative simplicity of the assets I'm developing).
Anyway, that's probably enough detail on this admittedly niche topic for now. If you've made it this far, I'd be interested any thoughts / approaches to this problem you've come up with, and whether procedural renaming is the most sensible solution. If any devs are purusing the forum, perhaps there could be some built-in functionality to deal with attribute/group naming conflicts, that either builds on this solution or tackles it a completely different way.
Found 48 posts.
Search results Show results as topic list.
Technical Discussion » Making digital assets: handling internal attributes / groups
- AndrewJBeard
- 50 posts
- Offline
Technical Discussion » Attaching geometry to objects in DOPs
- AndrewJBeard
- 50 posts
- Offline
I've got a tower of bricks in DOPs being collapsed a Magnet force, which itself references metaballs in a geometry node. At the moment the metaballs are static and don't move with the collapsing bricks, which is fine but I'd like to activate each metaball force at different times during the simulation, so it's best if they follow the simulated objects. How do I ‘attach’ the metaballs to certain bricks as they collapse so that the force they create moves with these bricks?
Is it effectively a constraint I need to set up (in which case I'm not sure that the constraint geometry required by the Bullet solver will work) or is there a simpler way? I don't need the metaballs to participate in the RBD simulation other than act sources of force to be applied to the RBD objects.
Thanks in advance,
Andrew
Is it effectively a constraint I need to set up (in which case I'm not sure that the constraint geometry required by the Bullet solver will work) or is there a simpler way? I don't need the metaballs to participate in the RBD simulation other than act sources of force to be applied to the RBD objects.
Thanks in advance,
Andrew
Technical Discussion » Varying Instanced Geometry
- AndrewJBeard
- 50 posts
- Offline
I've got a bunch of identical objects all wrapped up as a packed primitive, having been instanced by the Copy SOP. (A bunch of bricks stacked up in a tower ready for collapsing in DOPs, if you're interested). Nothing complex.
I'd like to vary the color (and nothing more) of each primitive, which I would have thought is accomplished by simply adding a Cd attribute to the points which represent the instanced geometry, and throwing a material shader at the object.
Sadly not.
I understand that both the Viewport and Mantra do something special with packed primitives (and other forms of instancing) that requires only one copy of the geometry to be retained in memory for efficiency and whatnot. But surely there's a way to add unique color to each instance?
Do I have to unpack my packed primitive in order to apply color to each primitive? Is there some limitation of instancing at the *geometry* level that prevents point attributes like color being used in shaders? Does it only work when instancing at the *object* level (which is what most of the H13 documentation on the subject seems to refer to)? Although, that said, I've tried both and had no luck with either.
Really thought I was just getting to grips with packed primitives until now. Please help. My colorless bricks are beginning to look a little sad
I'd like to vary the color (and nothing more) of each primitive, which I would have thought is accomplished by simply adding a Cd attribute to the points which represent the instanced geometry, and throwing a material shader at the object.
Sadly not.
I understand that both the Viewport and Mantra do something special with packed primitives (and other forms of instancing) that requires only one copy of the geometry to be retained in memory for efficiency and whatnot. But surely there's a way to add unique color to each instance?
Do I have to unpack my packed primitive in order to apply color to each primitive? Is there some limitation of instancing at the *geometry* level that prevents point attributes like color being used in shaders? Does it only work when instancing at the *object* level (which is what most of the H13 documentation on the subject seems to refer to)? Although, that said, I've tried both and had no luck with either.
Really thought I was just getting to grips with packed primitives until now. Please help. My colorless bricks are beginning to look a little sad
Technical Discussion » New Dark UI Color Scheme
- AndrewJBeard
- 50 posts
- Offline
Technical Discussion » New Dark UI Color Scheme
- AndrewJBeard
- 50 posts
- Offline
Okay, try the latest upload. Not sure I did anything regarding the dopesheet knob color, but doesn't seem to be purple on my system anymore.
Technical Discussion » New Dark UI Color Scheme
- AndrewJBeard
- 50 posts
- Offline
Technical Discussion » New Dark UI Color Scheme
- AndrewJBeard
- 50 posts
- Offline
MartybNz, what kind of keyframe is that you've created that shows up purple? Trying to find a way of replicating it on my system…?
Andrew
Andrew
Technical Discussion » New Dark UI Color Scheme
- AndrewJBeard
- 50 posts
- Offline
Technical Discussion » New Dark UI Color Scheme
- AndrewJBeard
- 50 posts
- Offline
Technical Discussion » New Dark UI Color Scheme
- AndrewJBeard
- 50 posts
- Offline
Technical Discussion » New Dark UI Color Scheme
- AndrewJBeard
- 50 posts
- Offline
Fixed! I think the white text on grey is more readable than black text on grey - for both light and dark viewport backgrounds - but see what you think.
Technical Discussion » New Dark UI Color Scheme
- AndrewJBeard
- 50 posts
- Offline
Technical Discussion » New Dark UI Color Scheme
- AndrewJBeard
- 50 posts
- Offline
Thanks MartybNz. Should now be fixed. I've updated the attachment in the original post.
Technical Discussion » New Dark UI Color Scheme
- AndrewJBeard
- 50 posts
- Offline
I’ve been working on a custom UI color scheme that I’d like to share with you for feedback. I found the built-in ‘Houdini Dark’ theme to be a little inconsistent and high-contrast in places, and set about developing my own from the ground up.
As the Exchange is now depreciated, and Orbolt.com doesn’t cater for color schemes, I’ve had to post my scheme file here as a zip file (see attached) - .hcs files are apparetly ‘not allowed’. Simply drop the unzipped file into your \houdiniXX.X\config directory and launch Houdini. The scheme “ajb Dark” should now be available in the Edit > Color Settings dialog. Let me know what you think.
*Important* I’ve not yet identified the purpose of every color variable featured in the default schemes (many are depreciated and there’s limited documentation available in the file) so I’ve set these unknowns to magenta (bright purple) as per SideFX practice. If you observe any bright purple elements in the UI let me know where and I’ll fix them – they’re not there by design! (It’s thanks to Wolfwood’s post back in 2007 that I was able to get as far as I have).
Improvements over the ‘Houdini Dark’ scheme (in my opinion) include:
As the Exchange is now depreciated, and Orbolt.com doesn’t cater for color schemes, I’ve had to post my scheme file here as a zip file (see attached) - .hcs files are apparetly ‘not allowed’. Simply drop the unzipped file into your \houdiniXX.X\config directory and launch Houdini. The scheme “ajb Dark” should now be available in the Edit > Color Settings dialog. Let me know what you think.
*Important* I’ve not yet identified the purpose of every color variable featured in the default schemes (many are depreciated and there’s limited documentation available in the file) so I’ve set these unknowns to magenta (bright purple) as per SideFX practice. If you observe any bright purple elements in the UI let me know where and I’ll fix them – they’re not there by design! (It’s thanks to Wolfwood’s post back in 2007 that I was able to get as far as I have).
Improvements over the ‘Houdini Dark’ scheme (in my opinion) include:
- * Softer and more consistent use of gradients for the base controls (can’t actually get away from gradients entirely).
* An ‘amber’ highlight / accent color that matches viewport selection color and is used more consistently throughout (including menus, as per the ‘Houdini Light’ scheme).
* Re-introduced specific channel colors from the ‘Houdini Light’ scheme (modified for the dark scheme) that follow the ‘red, green, blue’ pattern for channel triples.
* Brightened bevels on nodes giving them a sharper appearance (subtle but effective).
* Reduced intensity of parameter field colors which makes parameter text more readable.
* Reduced intensity of network context colors on pane headings and tweaked color slightly for better visual separation.
* Myriad other tweaks that you may not even notice.
I generated the color scheme file from an Excel spreadsheet I built which visualises the color variables in-sheet, with VBA code to export the .hcs file in one click. It’s not quite ready for prime-time yet but if there’s interest I’ll make it suitable for release and share it with you.
One final note: I’ve noticed a slight difference in the way H13 uses color scheme variables to H12.5 (which I originally developed for), and since I’m now targeting H13 and don’t have earlier versions installed you may notice more ‘purple’ artefacts in earlier versions. As above, just let me know where you spotted them and I’ll implement a fix.
Edited by - March 25, 2014 17:11:20
Technical Discussion » Point Weight In SHOPs
- AndrewJBeard
- 50 posts
- Offline
Yep, that's what I ended up going with. Can't think why we're not able to access the built-in Pw attribute, but nevermind.
Technical Discussion » Point Weight In SHOPs
- AndrewJBeard
- 50 posts
- Offline
Technical Discussion » Point Weight In SHOPs
- AndrewJBeard
- 50 posts
- Offline
Indeed, thanks, tamte. However, for reasons that are too complex to go into right now I'd like to use the built-in P attribute - the fourth component of position - in my SHOP, rather than a custom attribute. Do you know how to accomplish this?
Cheers,
AJB
Cheers,
AJB
Technical Discussion » Point Weight In SHOPs
- AndrewJBeard
- 50 posts
- Offline
How do I access the point weight attribute from geometry in a SHOP?
P is only a vector(3) and neither ‘Pw’, nor ‘weight’ or any other shorthand I can think of works.
P is only a vector(3) and neither ‘Pw’, nor ‘weight’ or any other shorthand I can think of works.
Technical Discussion » Transposing a channel
- AndrewJBeard
- 50 posts
- Offline
Hmm… for a minute there I thought all my work my Transpose Chop was for nowt ‘cos I hadn’t read about the Shuffle Chop properly. However, I think koen was asking for something a little different than what the Shuffle Chop can do - which is exactly what I created the Transpose Chop for: see attached.
A few words of warning: I haven't fully tested it on arbitrary data - only my own needs which was to transpose a channel of never-decreasing data in the range 0 to 1. I don't know what will happen if you try to give it a decreasing data set, or one that increases and decreases (although this latter case has no real meaning for a transpose operation since channels cannot ‘loop back’ on themselves).
I also haven't supplied a test hip as such (I'm lazy) - the attached file is just the raw Vop network. However you should get an idea from the network how I went about solving the problem. I forget the intricacies of why every node has to be there (and trust me, they all do) as I wrote it a while ago. Anyhow, the basic principle is that for each index the Vop iteratively ‘hones in’ on where the channel crosses a certain threshold and sets this as the new sample value. I recall using some clever base-2 logarithmic math to compute how many iterations were needed for a given channel length, but forget how this works exactly.
I'd be interested to know how you came to need this Chop, koen, as I've been using it myself for reparameterizing motion along curves and I keep getting stuck on the damn camera flipping when the view and tangent normals coincide. From what I've learned so far, only ‘pythagorean hodograph’ curves posses the property of uniform (i.e. not wierd) frenet frame rotation over their length, and the term alone was enough to scare me off following it up any further. My maths just ‘aint good enough.
Anyway, hope the Transpose Chop helps. If you modify it to account for more general cases (i.e. decreasing channel data) I’d love to hear back from you.
All the best,
Andrew
A few words of warning: I haven't fully tested it on arbitrary data - only my own needs which was to transpose a channel of never-decreasing data in the range 0 to 1. I don't know what will happen if you try to give it a decreasing data set, or one that increases and decreases (although this latter case has no real meaning for a transpose operation since channels cannot ‘loop back’ on themselves).
I also haven't supplied a test hip as such (I'm lazy) - the attached file is just the raw Vop network. However you should get an idea from the network how I went about solving the problem. I forget the intricacies of why every node has to be there (and trust me, they all do) as I wrote it a while ago. Anyhow, the basic principle is that for each index the Vop iteratively ‘hones in’ on where the channel crosses a certain threshold and sets this as the new sample value. I recall using some clever base-2 logarithmic math to compute how many iterations were needed for a given channel length, but forget how this works exactly.
I'd be interested to know how you came to need this Chop, koen, as I've been using it myself for reparameterizing motion along curves and I keep getting stuck on the damn camera flipping when the view and tangent normals coincide. From what I've learned so far, only ‘pythagorean hodograph’ curves posses the property of uniform (i.e. not wierd) frenet frame rotation over their length, and the term alone was enough to scare me off following it up any further. My maths just ‘aint good enough.
Anyway, hope the Transpose Chop helps. If you modify it to account for more general cases (i.e. decreasing channel data) I’d love to hear back from you.
All the best,
Andrew
Technical Discussion » Surface Curvature Shader
- AndrewJBeard
- 50 posts
- Offline
I'm trying to use derivatives in SHOPs to make a simple curvature shader, i.e. vary the surface color by the ‘sharpness’ of the surface curvature at that point.
I'd like to do this in world position space, so I figure I need to calculate dN/dP. Using the chain rule I've expanded to dN/dP = dN/ds . ds/dP which implies that I simply take the derivative of the surface normal and divide by dPds (and the same with dPdt.).
However this doesn't seem to create sensible results; dividing by dPds often results in colors way out of gamut (such that MPlay treats it as #.INF).
Does anyone have any suggestions as to how I might calculate surface curvature in world space in SHOPs?
Thanks,
Andrew
I'd like to do this in world position space, so I figure I need to calculate dN/dP. Using the chain rule I've expanded to dN/dP = dN/ds . ds/dP which implies that I simply take the derivative of the surface normal and divide by dPds (and the same with dPdt.).
However this doesn't seem to create sensible results; dividing by dPds often results in colors way out of gamut (such that MPlay treats it as #.INF).
Does anyone have any suggestions as to how I might calculate surface curvature in world space in SHOPs?
Thanks,
Andrew
-
- Quick Links