Search - User list
Full Version: Grass!
Root » Work in Progress » Grass!
neil_math_comp
Being a developer, and only having first heard of Houdini about 2 years ago, I've never actually made an asset before, though I've been meaning to. In prepping for a small demo on big data I'm putting together, I realized that I needed some grass. I checked on Orbolt, and it looks like there isn't anything there yet for grass, so I decided this would be the one. To go completely overboard, I wanted it to be able to vary from a single open polygon with widths and normals, to a ridiculously overmodelled, multi-leaf, tall grass that's a closed, manifold, 3D solid surface, based on real samples I collected last weekend of about 7 grass species (from 5cm to 300cm). It is a demo for big data after all. :wink:

The images below are of a few individual grass leaves made with the preliminary version of the asset. In case you were wondering, no, that's not a texture map or even a bump map; that's actually geometry for all of the veins up each leaf, 500,000 quads per leaf. There's a bit of point colour variation, but I haven't set up the controls I'd like for that yet; there are lots of dry spots and mould spots in real grass. I'd also like to set up some noise controls for more variability on the blade portion. (Also, there are a few bugs to work out, it looks like from the close-up!)

Of course, I still need to make the low-res versions, the combining of multiple leaves for tall grass, set up some nice presets for generating different species easily, and maybe even put together a grass clumping tool to aid with making big fields with billions of grass plants.

I've been bothering the rest of R&D with this recent grass modelling obsession of mine, so I figured I should ask some artists: what sorts of things would artists be looking for in a grass generator?
anon_user_37409885
Whoah - very nice!

I could always use grass for mountain/alpine shots - dry tussocks and green meadows around streams. Being able to have the camera in the grass and jib up would be great, looks like you have the detail there so coolness. Reaction to breeze, wind etc and rain would be rad.
neil_math_comp
MartybNz
Whoah - very nice!

I could always use grass for mountain/alpine shots - dry tussocks and green meadows around streams. Being able to have the camera in the grass and jib up would be great, looks like you have the detail there so coolness.
Thanks!

Reaction to breeze, wind etc and rain would be rad.
That would be cool! I think I can do something relatively simple if I assume that the grass immediately goes to its equilibrium position given a force volume and grass stiffness parameters or something like that. For actual reaction, I'd need at least a SOP solver, which would take some experimentation.

I have the leaf generation split up into an AttribWrangle that creates a single polygon curve with a huge number of parameters (e.g. curl, bend, turn, twist, width, normal, tangent, bitangent, thickness, …) for each point, then another that takes that and creates the surface, so I'd only need to affect what the first one outputs in order to respond to a simulation.
symek
Not that I have anything to say about the grass (except it's lovely though perversely impractical) but I really like the idea of Sesi devs running threads like that, possibly even blogs (oh!, did I say “blog”?). Nothing is better for mutual understanding like being the other… e… (mute?)

Say, considering the amount of controversy and various expectations about Mantra standard material, shouldn't it be tinkered in public…? This closed-beta program is good for a new stuff, not necessarily for the enhencements.
neil_math_comp
SYmek
though perversely impractical
Haha, yep, though I'm making a low-res generator too, so that you can have the 1-poly-curve and 2-poly-curve versions too, and all the way up. I've also been making an adaptive curve resampler in VEX, so that should come in handy for making lower-res versions.

but I really like the idea of Sesi devs running threads like that, possibly even blogs (oh!, did I say “blog”?). Nothing is better for mutual understanding like being the other… e… (mute?)

Say, considering the amount of controversy and various expectations about Mantra standard material, shouldn't it be tinkered in public…? This closed-beta program is good for a new stuff, not necessarily for the enhencements.
I'm not one to be making any decisions on communication or other initiatives, but I have found an embarrassing number of small-but-painful bugs while using Houdini just a bit over the past few weeks. There are a bunch of others that I already knew about, but that are much more annoying when actually using Houdini to try to accomplish something than when just testing something. For example, the Transform SOP by default not only destroys vertex normals, but computes new point normals and then writes them back over the vertex normals, so it's not even clear that it did so; it just looks wrong for no apparent reason. Also, missing the tab key slightly and getting a file dialog, among many other painful single-character shortcut keys, need to go; I've borked my UI in unknown ways far too many times. I've also discovered an incredible loathing for the ForEach SOP, etc.

I think part of the difficulty with the small-but-painful bugs is that new users, when they encounter something going wrong, usually assume that it's just them doing something wrong, and long-time users have already found workarounds for most everything, so they're less likely to encounter or report many of the worst issues. In the name of expediency, some long-time users may even tell the new users to just use the workarounds, so they learn the workarounds as the “right” way to do things, and never even realize there's an issue worth reporting. Thankfully, there's at least one guy who's been submitting tons of these small bugs, most days for a year or so. He submitted something like 45 bugs one day in early January.

However, even the small-but-painful bugs that are reported have a strong tendency to fall off the back burner and become forgotten, unless other people report having the same problem. I try to do some of the easier ones as they come in, (like why the hell did PolyFrame not support naming the normal attribute N? and why didn't PolyExtrude support transferring groups to the new geometry?), but it's tough to make time for them, because even checking whether a bug may only take a couple hours to fix might take a half hour or more. I also have a mounting pile of FBX bugs that may only require a few lines to be changed each, but that each take ages to investigate and figure out exactly what's wrong.

Wow, that was a lot of text. Maybe I should blog.
anon_user_37409885
ndickson
I think part of the difficulty with the small-but-painful bugs is that new users, when they encounter something going wrong, usually assume that it's just them doing something wrong, and long-time users have already found workarounds for most everything, so they're less likely to encounter or report many of the worst issues.

This is an important point. The major challenge in reporting bugs is to understand the methodical nature that a developer needs the bug to be reported is almost the opposite of the way an artist works with their tools. An analogy would be like asking a pianist to explain the exact sequence and movement of their fingers to recreate a problem with their piano.
symek
ndickson
Wow, that was a lot of text. Maybe I should blog.

You see, it's spreading! Dangerous word.

Thank you for your comments. Yes, small bugs reports are kind of frustrating because it's somtimes harder to reproduce it, than get used to. I don't do a lot of shots, more coding and such, but whenever I sit to the actual show I'm unpleasantly surprised how many things in the pipeline don't work the way I was sure they do…

Who said programmers should use their own software as an atonement and precaution?
animatrix_
I reported the PolyFrame ones, bless you for fixing them There were 3 issues, and all of them are fixed in H13.

Not sure how you guys are doing it, but at Bioware we used to have bug weeks sometimes.

Btw is this DA your personal project or SESI's? Are you gonna sell it? It would also be cool to release the low-level ops you create for this DA separately, i.e. your Resample Curve SOP in VEX.

I love it when I am making a generic DA, new opportunities open up to create other generic ones to accomplish the first one.
neil_math_comp
pusat
is this DA your personal project or SESI's?
It's a personal project on my own time and in Apprentice, though I'm sure people would be fine with me using FX via work. (but how else would I discover today that the VC11 installer may forcibly restart one's computer without warning? GAGH!) I'm doing the demo for SESI, though.

Are you gonna sell it? It would also be cool to release the low-level ops you create for this DA separately, i.e. your Resample Curve SOP in VEX.
I'll provide them for free on Orbolt, with all access, partly because I know that other people would prefer to do something completely different with it, or just learn from it, so they may need all of the details. As a warning, being a programmer, I did almost everything in AttribWrangle, and I filed bugs/RFEs for most of the things that I couldn't do inside AttribWrangle. :wink:

I love it when I am making a generic DA, new opportunities open up to create other generic ones to accomplish the first one.
Definitely! The adaptive curve resampling turned out to be quite simple, after I thought of a way to do it in linear time, especially when I realized that the points didn't have to be exactly on the original curve(s). My test version only considers position; it'll be a bit more complicated/tedious to add the right tolerance checks for all of the other attributes that matter. There's no way to iterate through all attributes of some type in AttribWrangle, so I'll have to have special cases for each, or at least make a fixed array of attribute names and an array of their types, or a multiparm, or something like that. :roll:

Also, I discovered, while doing the grass generation, that if you have infinitesimal rotations, the rotation order doesn't matter, (the matrices commute), and integrating them up to finite values, always alternating axes, you get something equivalent to the axis-angle rotation vector (theta_x, theta_y, theta_z). The latter took a bit more work to derive than the former.
animatrix_
SESI should have something like SESI Fridays similar to Google Fridays. It could spark a lot of great ideas, as well as fix issues that weren't as apparent to developers from a user's POV.

I didn't know SESI devs can submit RFEs themselves. I wish you were responsible for the Wrangle SOPs, VEX, then you would have added all those things you thought were missing

Because I came across the exact limitations you are describing. There is some detail on it in bug ID 58393 (support ticket 16134).

Since you are creating a generator SOP I assume (?), I imagine you also came across things like having attributes to exist before you can set them in Wrangle SOPs, for colors, etc.

I wrote some generic code that handles multiple float types using arrays in my AttribBlur SOP, but that's limited to Point Wrangle for one because of the import function, and doesn't allow for @ syntax. I also had to use a Foreach SOP to iterate on multiple attributes.

On paper Wrangle SOPs look great. But it's only after you start using them for non-trivial cases, you start to see the limitations and inconsistencies. For example implicit normal access @N doesn't work in AttribWrangle but does in PointWrangle.

It would be awesome if we had generics in VEX. The ability to uniformly work with attributes in VEX is paramount for digital assets. If we had this, the use of Foreach SOP to support multiple attributes would be eliminated, which could provide significant performance improvements, i.e. going through all attributes annd performing a single point cloud operation per point for blending, etc, vs one pcloud operation for each attribute using Foreach.

I am really interested in checking out your grass DA, and the low-level OPs that make it up like the adaptive curve resampler, etc. Does it support multiple curves? What about closed curves?

The matrix operations also sound interesting. I haven't realized that outcome you explained.

You grass DA reminded me this picture I have seen long ago because of the grass/leaf pattern/veins:

neil_math_comp
pusat
I wish you were responsible for the Wrangle SOPs, VEX, then you would have added all those things you thought were missing
Well, I'm responsible for polysoups, and a bunch of polysoup RFEs/bugs that I assigned to myself haven't gotten addressed, because they're not quite as simple as they sound, for various reasons, and there's been a ton of more critical stuff to do, pushing those things back.

Because I came across the exact limitations you are describing. There is some detail on it in bug ID 58393 (support ticket 16134).

Since you are creating a generator SOP I assume (?), I imagine you also came across things like having attributes to exist before you can set them in Wrangle SOPs, for colors, etc.
Yep. I just have a couple AttribCreate nodes with a big ton of attributes, to put in the input of AttribWrangle. I think I submitted two bugs/RFEs for that; one that you need at least a Null SOP as input, and one that you can't create attributes.

I wrote some generic code that handles multiple float types using arrays in my AttribBlur SOP, but that's limited to Point Wrangle for one because of the import function, and doesn't allow for @ syntax. I also had to use a Foreach SOP to iterate on multiple attributes.

On paper Wrangle SOPs look great. But it's only after you start using them for non-trivial cases, you start to see the limitations and inconsistencies. For example implicit normal access @N doesn't work in AttribWrangle but does in PointWrangle.

It would be awesome if we had generics in VEX. The ability to uniformly work with attributes in VEX is paramount for digital assets. If we had this, the use of Foreach SOP to support multiple attributes would be eliminated, which could provide significant performance improvements, i.e. going through all attributes annd performing a single point cloud operation per point for blending, etc, vs one pcloud operation for each attribute using Foreach.
There are a bunch of things that would be good to add/improve/fix, now that AttribWrangle is starting to grow in popularity.

I am really interested in checking out your grass DA, and the low-level OPs that make it up like the adaptive curve resampler, etc. Does it support multiple curves?
Yep. It's just an AttribWrangle parallelized over primitives. It should work for resampling NURB, Bezier, and polygon curves, but the output is always polygon curves.

What about closed curves?
Good question. For closed NURB/Bezier curves, it should probably do almost what's expected, except that there'll be a point for u=0 and a point for u=1. Hopefully I can check using primintrinsic(0,“closed”,@primnum) and primintrinsic(0,“typename”,@primnum) to fix it in that case. For closed polygons, the meaning of the (u,v,w) space is different than for open polygons, and I'm not sure I could do what people might expect for it; I could probably make it act as if they were open but come back to their start points.

You grass DA reminded me this picture I have seen long ago because of the grass/leaf pattern/veins:
Cool
animatrix_
Hehe I submitted that one as well regarding the use of AttribWrangle as a generator without using a null (ID# 58193). I have been told it would make more sense to create a separate GeneratorWrangler or better named variant, which just has the AttribWrangle + null + detail mode. Although ironically the PointWrangle has a null inside.

Recently I also made a new SOP called AttribCurveTransfer that lets you transfer point attributes between two curves using arc-length (average spline in this case) or uniform parameterization.

Can I ask how you approximated point positions on a NURBS curve? Did you generate Greville points? Did you use the primuv function? There are a few gotchas with NURBS curves though. For example intrinsic:knots can be non-normalized which has to be normalized using the Basis SOP for the UV texture to generate normalized UV values.

The output can't be NURBS though I am sure you know as addprim doesn't support NURBS curves. I sent a RFE though. I think it would be useful so you can do it all in VEX and is not far off from polygon curves.

A Variables to Create parameter would be very handy and be inline with how Houdini works. Every attribute you create as limited by the Attributes to Create would also create a variable automatically as limited by the Variables to Create parameter, which would be * by default.

Handling closed curves the way you explain sounds reasonable reasonable. I think I do that for my Path Follow SOP, otherwise PolyFrame generates very different bitangents for closed curves.

Actually with all these RFEs people are submitting, I bet a lot of them are saved in separate reports. Because everyone words these differently and who is gonna remember the core idea being requested and file them under the same report.

That's why I think SESI would benefit from a UserVoice based RFE system that could be monitored by the community and similar ideas are gathered as a single RFE, as well as allow people see other RFEs and weigh in on ones that matter them the most.

Anyway I don't want to derail your thread

Actually are you using guides for your DA? I think the ability to see the outline of a single grass blade using NURBS curves could be quite useful and interactive to see bend, twist, and other modifications. I did a similar thing using a hollow box made up of NURBS curves. Deforming it showed you very clearly how a particular deformer deformed the space around the geometry. As you know if you do it otherwise, i.e. using an actual box, you will have divisions across the faces, which will not be as clean looking and clutter the actual geometry being deformed.



Houdini's guide system is legendary as it's leveraging the whole power of SOPs
neil_math_comp
pusat
Recently I also made a new SOP called AttribCurveTransfer that lets you transfer point attributes between two curves using arc-length (average spline in this case) or uniform parameterization.
Cool.

Can I ask how you approximated point positions on a NURBS curve? Did you generate Greville points? Did you use the primuv function?
I'm using primuv so that I don't have to worry about the difficult stuff. :wink: My initial version used a fixed number of steps, but I'm changing that to use adaptive stepping too, so that it's not so slow for faraway curves.

I've also realized that the way I'm checking tolerance in constant time per step is too much erring on the “safe” side. If you have a perfectly straight curve, but non-uniformly-spaced points along it, it'll produce a curve with more than 2 points, because it's checking tolerance in 3 dimensions instead of just the 2 that are perpendicular to the line. Fixing it without making it linear time per step will mean much more complicated code, unfortunately.

Actually are you using guides for your DA? I think the ability to see the outline of a single grass blade using NURBS curves could be quite useful and interactive to see bend, twist, and other modifications.
There are a ridiculous number of parameters on it right now; guides and scripted presets would make it much easier. The difficulty is designing the right guides and getting them all to work. I've never actually made a guide, so I'll have to learn. For the large-scale grass generation, for fields of grass and such, guides may make things too complicated. A menu parameter that sets other parameters to presets for different types, and a more limited number of parameters for variation would probably make it easier.
animatrix_
How do you use adaptive stepping? Do you inspect if the subsequent points curve greater than a threshold? I haven't done anything like that but when you only check in 2 dimensions that is the plane perpendicular to your line, will it really make it execute in non-linear time? I thought it would still be fast. Are calculating this plane as you move along the curve?

I might be understanding your linear time per step wrong though

There is also a way to measure Curvature using the Measure SOP. Have you used that? I don't know if it would work in your case, but it's interesting.

Making guides is easy, just point it to your resulting SOP. It will be hard to come up with a useful guide like you said. Let me also tell you that sometimes a fancy guide can end up being much slower than the tool itself. I had to remove such a guide from my Best Fit Plane SOP because the slick looking guide that I generated using the source and target points took a lot more cooking time and memory and crashed on my system. The tool itself uses almost no memory as I only create 2 detail attributes. But the guide was killing it

Are you gonna be using the built-in presets functionality of Houdini or make buttons on the DA to do that similar to the Wrangle SOPs? The latter option is not optimal in my opinion. They also don't save spare parameters unless you script them I believe.
neil_math_comp
pusat
How do you use adaptive stepping?
TL;DR: Very carefully.

To be clear, the “stepping” I'm talking about in this paragraph is just the stepping through the values of u that I'll be testing to see if they'll need points in the output. I'll be computing the tolerance at the start point (u=0), carefully adjust u until I get something that's about half of that tolerance away, (making sure to also check backward, in case the tolerance at u is quite different). Since it's within the tolerance of the first point (and vice versa), it'll never need an output point there, but it'll be used for the initial guess of the step size for the next step. The next step, I'll take a step of the same size as before, verify that the points are less than a certain portion of their tolerances apart, and if they aren't, reduce the step size by some factor repeatedly, until they are, but with a lower limit to avoid freezing in the case where the curve crosses the camera position. If the step is too safe, (too small of a portion of the tolerances), I'll increase the step size until they're at least a minimum portion of the tolerances, but with an upper limit of 0.5/(nVertices-1), to avoid problems with curves that circle around repeatedly.

I haven't done anything like that but when you only check in 2 dimensions that is the plane perpendicular to your line, will it really make it execute in non-linear time?
As I step along, I need to check whether there still a way to cast a straight ray from the start of the latest segment that will be within the tolerance of every value of u examined up to this value of u. A brute force way of doing this means that at each step, you check a line directly from the start of the segment to the step's u, and so for each step you've already done, you have to re-examine whether the new line is still within the tolerance of each of those steps. That's order n^2 checks in total, where n is the number of steps you end up doing per segment.

To avoid that, I have to compute the permissible solid angle region (circle, which is what I meant by 2D) from the start of the segment to the current step's u, and then track the intersection of that and all previous permissible regions. If the intersection is empty, there's no line segment that will work; if the intersection is empty, any line segment of an acceptable length that goes in the direction of the remaining permissible region will work. Of course, if I use the exact intersection of the regions (circles), the description of the region becomes linear in n to check for membership. However, I can make it a bit suboptimal and just keep the maximal circle that fits inside the intersection, which will let it still be constant time to check against on every step.

Are you gonna be using the built-in presets functionality of Houdini or make buttons on the DA to do that similar to the Wrangle SOPs?
There was some issue with using the built-in presets functionality, but I can't remember what it is right now. Maybe that it can't be shipped with the asset?
animatrix_
Hi,

Any new info about your asset? Or an ETA? I was hoping it would be ready before xmas

ndickson
There was some issue with using the built-in presets functionality, but I can't remember what it is right now. Maybe that it can't be shipped with the asset?

No they worked fine in my experience but when Orbolt was first launched, the presets didn't show up for namespaced HDAs, but that's fixed long ago.

You might also not be aware of this which probably might not impact you but Orbolt doesn't allow uploading HDAs of the same name but of different types. Unlike Houdini where you can have add (vop) and add (sop), to Orbolt they are the same, which makes low-level HDAs that I make for myself and later share on Orbolt harder, as I am very picky about names and don't like unnecessary prefix/suffixes since Houdini doesn't need them. I use namespaces though so I don't have to worry about name collisions with the buil-in operators.

I did think of a new workaround recently that I will use to upload the same name HDAs. If I remember correctly the version numbers as part of the HDA fullname registers as a new asset in the store. So I guess I can make that compromise
Sadjad Rabiee
Really Useful Topic 8)
Skybar
Did you ever complete the Grasset or how is it going?
neil_math_comp
Skybar
Did you ever complete the Grasset or how is it going?
Alas, it's mostly fallen off the backburner, like many of my side projects.

The adaptive curve resampling for background grass (or fur) seems to work fairly well, but it's extremely slow; maybe ~20s for a couple hundred thousand curves, and only considering position in the refinement, not other attributes. As I discovered, taking width into account is also critical, else you can end up with everything being consistently darker, because there's less coverage farther out with cases like grass and fur that taper mostly near the end of the curve. You can see that effect by rendering some fur, then decreasing the dicing quality to 0.1 and re-rendering. More recently, I've tried to figure out a faster approach, given some assumptions, but the math explodes pretty quickly. I could probably slap together something that's quick-and-dirty and okay 90% of the time, but getting things pixel-perfect is a giant mess.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB