FloraForge: Procedural Generation of Editable and Analysis-Ready 3D Plant Geometric Models Using LLM-Assisted Template Design
This repository accompanies the paper FloraForge (see Citation below). It provides the LLM-designed Python generators that build procedural, editable 3D plant geometry from a YAML/JSON config file — a monocot template (maize, maize_procedural_plant.py) and a dicot template (soybean / mung bean, mungbean_soybean_procedural_plant.py). The generators produce NURBS/B-spline surfaces for stems and leaves and export triangulated geometry for downstream use (e.g., CAD, meshing, rendering).
Maize scope: culm + leaves (no tassel/ear/roots; no sheath). Leaf bases are hard-grafted to the culm for clean attachment. The stem can be curved using per-internode curvature terms.
The natural-language prompt transcripts from the LLM co-design sessions that produced these generators (one maize session and three soybean sessions, using OpenAI GPT-5 Thinking) are in Plant_refinement_prompts/ — see that folder's README for a session-by-session guide. Example Plant Descriptors are in Plant_descriptor_examples/.
python -m venv .venv && source .venv/bin/activate # on Windows: .venv\Scripts\activate
pip install numpy geomdl pyyamlpython maize_procedural_plant.py --config maize_V1.yaml- Inputs:
maize_V1.yaml(or any YAML/JSON config following the schema below). - Outputs:
*.stl: triangulated mesh (all surfaces)*.dat: SMESH/mesh exchange file produced bygeomdl.exchange.export_smesh
Set output names in the config (see outfile_stl / outfile_smesh), otherwise defaults are used.
Below are the top‑level keys the script understands, grouped by function. Types and units are noted; unless stated, angles are in degrees, lengths in cm.
seed(int, default 12345): RNG seed for reproducibility.sections(int, default 24): Culm ring resolution (angular samples) for the stem surface.curve-segments(int, default 16): Discrete steps per internode along the centerline (controls curvature sampling fidelity).outfile_stl(str): Path to output STL (if missing, derived fromoutfileor defaultmaize.stl).outfile(str, optional): Base name; if provided without.stl, the script appends.stl.outfile_smesh(str, optional): Path for the SMESH/.datexport (defaults to the same stem as STL with.dat).
node-z(list[float], required): Absolute heights of nodes (bottom→top), strictly increasing, in cm. Defines internodes and leaf attachment levels.stem-diameter-mm(list[float]) orstem-radius-mm(list[float]): Per‑node stem sizing in mm. One value per node; determines culm radius profile (interpolated along internodes). If omitted, a default taper is used.
-
stalk-kappa(float or list[float], default 0.0): Curvature magnitude per internode (1/cm). Scalar broadcasts to all nodes. -
stalk-bend-az-deg(float or list[float], default 0.0): Bending plane azimuth per internode (0° = +x toward +y as azimuth increases, global +z is up). -
stalk-kappa-terms:- Either a single list of terms (broadcast to all internodes)
- Or a list‑of‑lists (one list per internode)
- Each term is:
- kappa: <float, 1/cm> az-deg: <float, deg> span: [s0, s1] # optional, along the internode from 0..1
Use this to create multi‑axis, piecewise curvature within an internode (fine control of the centerline).
-
apical-extend-cm(float, default 8.0): Extends the stem above the last node by this length (keeps the apex continuous).
leaf-az-base-deg(float, default 0.0): Base azimuth for the first leaf.leaf-az-noise-deg(float, default 0.0): Uniform random noise ± around each leaf’s azimuth.leaf-az-deg(float or list[float], optional): Explicit per‑node azimuth(s). If omitted, leaves alternate 180° starting fromleaf-az-base-deg(with optional noise).leaf-pitch-deg(float or list[float], optional): Leaf pitch (positive = faces upward). Negative pitches are internally clamped to up‑facing.leaf-roll-deg(float or list[float], default 0.0): Roll about the leaf’s longitudinal axis.
leaf-base-attach-u(float in 0..1, default 0.12): Distance from base along leaf (paramu) where soft blending to the culm ends.leaf-base-offset-mm(float, default 0.8): Radial offset (mm) pushing the base slightly off the culm radius to avoid z‑fighting.leaf-base-min-arc-deg(float, default 6.0): Minimum circumferential arc (deg) sampled on the culm for the graft rows.leaf-base-graft-rows(int, default 2): Number of hard‑grafted leaf control‑net rows replaced by culm ring samples.leaf-base-arc-deg(float, optional): Fixed arc width for the graft (if omitted, estimated from the leaf base chord).leaf-base-axial-cm(float, default 0.8): Axial distance along the culm over which the hard‑grafted rows are placed.
leaves:
enabled: true
delta: 0.02 # surface evaluation density for leaves
globals: # defaults for all nodes (can be overridden per-node)
length: 60.0 # or length_cm
width: 9.0 # or width_cm (base width; tapers to 0 at tip)
width_pow: 1.3 # taper exponent (bigger → faster taper)
ctrl_u: 11 # control-net rows (longitudinal)
ctrl_v: 5 # control-net cols (spanwise)
camber: 0.018 # transverse camber amplitude (× length)
camber_pow: 1.6 # camber falloff from midrib to edge
bend: 0.020 # upward arch amplitude along length (× length)
twist: 10.0 # twist (deg) from base→tip
fold: 0.0 # V‑fold angle (deg) about midrib; 0 disables
fold_pow: 1.2 # fold dependence across the span
fold_u_pow: 1.0 # fold envelope along length
skew: 0.02 # asymmetry (lateral bias along length)
midrib_offset: 0.0 # shifts midrib toward left/right (− to +)
left_bias: 0.0 # widens left side (vj<0) proportionally
right_bias: 0.0 # widens right side (vj>0) proportionally
leaf_yaw_deg: 0.0 # local yaw tweak
leaf_pitch_deg: 12.0 # enforced non‑negative (up‑facing)
leaf_roll_deg: 0.0
nodes:
1: # per-node overrides for node index 1 (1‑based)
length: 55.0
leaf-bend-hinges:
- u0: 0.35 # start of rotation along leaf length (0..1)
angle-deg: 12.0 # rotation magnitude
axis: "B" # local axis: 'B' (span), 'N' (normal), 'T' (tangent)
smooth: 0.03 # smoothing width in u (0 = sharp hinge)
2:
enabled: trueNotes:
enabled(bool) can disable leaves globally or per node.- Any key under
globalscan be overridden undernodes:<i>. leaf-bend-hingesapplies additional local rotations to portions of the leaf for realistic shapes.
seed: 12345
sections: 24
curve-segments: 16
outfile_stl: maize.stl
outfile_smesh: maize.dat
# Node heights (cm), strictly increasing
node-z: [12, 25, 38, 52, 67, 83]
# Stem sizing (choose one of the following)
# stem-diameter-mm: [25, 23, 21, 19, 17, 15]
stem-radius-mm: [12.5, 11.5, 10.5, 9.5, 8.5, 7.5]
# Curvature (global or via terms)
stalk-kappa: 0.0
stalk-bend-az-deg: 0.0
# stalk-kappa-terms:
# - { kappa: 0.04, az-deg: 45, span: [0.0, 0.6] }
# - { kappa: 0.03, az-deg: 120, span: [0.6, 1.0] }
apical-extend-cm: 8.0
# Leaf phyllotaxy & tilt
leaf-az-base-deg: 0.0
leaf-az-noise-deg: 2.0
# leaf-az-deg: [0, 180, 0, 180, 0, 180]
leaf-pitch-deg: 12
leaf-roll-deg: 0
# Base graft
leaf-base-attach-u: 0.12
leaf-base-offset-mm: 0.8
leaf-base-min-arc-deg: 6.0
leaf-base-graft-rows: 2
leaf-base-axial-cm: 0.8
leaves:
enabled: true
delta: 0.02
globals:
length: 60.0
width: 9.0
width_pow: 1.3
ctrl_u: 11
ctrl_v: 5
camber: 0.018
camber_pow: 1.6
bend: 0.020
twist: 10.0
fold: 0.0
fold_pow: 1.2
fold_u_pow: 1.0
skew: 0.02
midrib_offset: 0.0
left_bias: 0.0
right_bias: 0.0
leaf_yaw_deg: 0.0
leaf_pitch_deg: 12.0
leaf_roll_deg: 0.0
nodes:
1:
length: 55.0
leaf-bend-hinges:
- { u0: 0.35, angle-deg: 12.0, axis: "B", smooth: 0.03 }- STL (
outfile_stl): triangulated mesh of stem + leaves for visualization or printing. - SMESH/
.dat(outfile_smesh): mesh exchange file exported viageomdlfor meshing/analysis pipelines.
node-zmust be strictly increasing (base to top). If you get an error, check ordering.- If you supply per‑node arrays (e.g.,
stem-radius-mm,leaf-pitch-deg), their lengths must match the number of nodes. - If
leaf-az-degis omitted, azimuths alternate by 180° automatically starting fromleaf-az-base-deg(+ noise). - Negative
leaf_pitch_degis clamped to up‑facing internally. - Use
stalk-kappa-termsto sculpt realistic, multi‑axis bending within an internode.
If you use FloraForge, please cite:
Hadadi, M., Jubery, T. Z., Schnable, P. S., Singh, A., Benes, B., Krishnamurthy, A., & Ganapathysubramanian, B. (2026). FloraForge: Procedural Generation of Editable and Analysis-Ready 3D Plant Geometric Models Using LLM-Assisted Template Design. Smart Agricultural Technology. https://doi.org/10.1016/j.atech.2026.102316
@article{hadadi2026floraforge,
title = {FloraForge: Procedural Generation of Editable and Analysis-Ready 3D Plant Geometric Models Using LLM-Assisted Template Design},
author = {Hadadi, Mozhgan and Jubery, Talukder Z. and Schnable, Patrick S. and Singh, Arti and Benes, Bedrich and Krishnamurthy, Adarsh and Ganapathysubramanian, Baskar},
journal = {Smart Agricultural Technology},
year = {2026},
doi = {10.1016/j.atech.2026.102316}
}