Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "flare" option for the first level of branches off trunk #54

Open
jayfield1979 opened this issue Jul 27, 2021 · 10 comments
Open

Add "flare" option for the first level of branches off trunk #54

jayfield1979 opened this issue Jul 27, 2021 · 10 comments
Assignees

Comments

@jayfield1979
Copy link

Certainly for the larger trees such as Oak, the ability to add "flares" to the branch start would really help them look less like they're rammed into the trunk mesh. I have been manually doing this for the lower branches on my trees as illustrated below:

image

@samipfjo
Copy link
Contributor

Ooh excellent idea. I think I'll tackle this one next.

@samipfjo
Copy link
Contributor

samipfjo commented Jul 30, 2021

As with many problems in programming, this turns out to be easier said than done. I've been playing with the flare set at the bottom of gen.py::Tree.radius_at_offset() (under a check for stem.depth == 1), but this does not account for the now-obvious slimming of the trunk as the height increases. That's my current snag. I'll come back to it with a fresh mind in a few days. Any thoughts in the meantime are welcome.

@friggog
Copy link
Owner

friggog commented Jul 31, 2021

I think the flare is just a multiplier of the base stem diameter - which should already reduce going up the trunk? Or is it that you want the taper amount to also reduce going up the trunk as smaller branches shouldn’t taper?

Either way I think you’re in the right place and should have all the info required

tree-gen/parametric/gen.py

Lines 993 to 1002 in 0b0bc62

def calc_stem_radius(self, stem):
"""Calculate radius of this stem as defined in paper"""
if stem.depth == 0: # trunk
result = stem.length * self.param.ratio * self.param.radius_mod[0]
else: # other
result = self.param.radius_mod[stem.depth] * stem.parent.radius * pow((
stem.length / stem.parent.length), self.param.ratio_power)
result = max(0.005, result)
result = min(stem.radius_limit, result)
return result
defines the base radius of a stem which might help you figure out changing things as you move along the parent stem

@samipfjo
Copy link
Contributor

Yeah, it's an issue with flare on the smaller branches near the canopy, where the flare on the 1st level of branches clips outside of the trunk's slimmer diameter. Thanks for the snippet link; I'll check out that section when I get back to it.

@jayfield1979
Copy link
Author

Maybe you only need to perform this on the branches that are the first 50% up the trunk?

@samipfjo
Copy link
Contributor

samipfjo commented Jul 31, 2021

That won't work for trees that don't taper their trunk, ex. Douglas Firs.

Edit:
That example was kind of dumb of me. Douglas Firs do taper, I just don't think 50% up wouldn't work with them taper rate wise.

@samipfjo
Copy link
Contributor

samipfjo commented Aug 3, 2021

Found a cheesy way to find the height of the branch. Now that I have that, we can scale and limit by height. Will need to play around with this more to get a feel for how it should be implemented. L1129 for context

elif stem.depth == 1 and z_1 < .05:  # Check position on branch; z_1 is scaled by offset
    # TODO :: Save trunk root pos to prevent unnecessary lookups
    branch_height = stem.curve.bezier_points[0].co.z - self.branches_curve.splines[0].bezier_points[0].co.z  # branch root pos - trunk root pos
    distance_to_top = self.trunk_length - branch_height

    if branch_height < self.trunk_length * .6:  # TODO :: Add parameter for % of height to stop at
        # TODO :: Scale by distance_to_top
        y_val = max(0, 1 - 18 * z_1)  # 23 is highest
        flare = ((pow(100, y_val) - 1) / 100) + 1
        radius *= flare

@friggog
Copy link
Owner

friggog commented Aug 8, 2021

stem.length / stem.parent.length gives perhaps a simpler proxy for distance along the trunk/parent branch. Using the z coordinate will ignore any curvature of the trunk so isn't that precise. I agree the best solution is probably just to add a position_on_parent parameter to each steam which stores the fractional distance along the parent stem at which the current stem originates.

@samipfjo
Copy link
Contributor

samipfjo commented Aug 8, 2021

I've had another idea that wouldn't require an additional parameter. Now that the branch curves are separate we can walk Branches1, grab the first few bezier points, and scale them by a decreasing multiplier. I've already written a function to find the nearest handle on the trunk (on the z-axis) and return it's width. That would allow it to be done retroactively as an Operator as well.

@samipfjo
Copy link
Contributor

samipfjo commented Aug 8, 2021

Oh wow my reading comprehension apparently sucks right after I wake up. Yeah, using the z coordinate would be less precise for sure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants