diff --git a/blender/generate_scene.py b/blender/generate_scene.py index 400b812..a8cd113 100644 --- a/blender/generate_scene.py +++ b/blender/generate_scene.py @@ -91,40 +91,6 @@ def _assemble_building(ring, way_id, tag, args, buildings_c, building_mats): building_mats, buildings_c) return 1, int(industrial), ring - -def _add_polyhaven_trees(positions, collection): - """Scatter island_tree_01 instances at `positions`. - - positions is a list of (x, y, height) tuples as gathered by the two - tree-collecting loops (point nodes + tree_row samples). - """ - variants = _tree.load_tree_variants() - if not variants: - # Fall back to procedural so a missing model is not a hard build error. - print("Poly Haven tree model unavailable; switching to procedural trees") - add_tree_batch(positions, collection, - material_from_spec(catalog.MATERIALS["tree_trunk"]), - material_from_spec(catalog.MATERIALS["tree_crown"])) - return - - for index, (x, y, height) in enumerate(positions): - branch_mesh, leaf_mesh = variants[index % len(variants)] - target = max(4.0, height) - factor = target / 3.2 - - b_obj = bpy.data.objects.new(f"Tree_PH_{index:03d}_Branch", branch_mesh) - b_obj.location = (x, y, 0.0) - b_obj.scale = (factor, factor, factor) - b_obj.rotation_euler = (0, 0, (index * 1.61803398875) % 1.0 * math.tau) - collection.objects.link(b_obj) - - l_obj = bpy.data.objects.new(f"Tree_PH_{index:03d}_Leaf", leaf_mesh) - l_obj.location = (x, y, 0.0) - l_obj.scale = (factor, factor, factor) - l_obj.rotation_euler = (0, 0, (index * 1.61803398875) % 1.0 * math.tau) - collection.objects.link(l_obj) - - MODEL_ROOT = os.path.abspath(os.path.join( os.path.dirname(__file__), "..", "assets", "models", "polyhaven" )) @@ -749,7 +715,7 @@ def build(args): if trees: tree_style = args.get("tree_style") if tree_style == "polyhaven": - _add_polyhaven_trees(trees, props_c) + _tree.assemble(trees, props_c) elif tree_style == "natural": tree_trunk = material_from_spec(catalog.MATERIALS["tree_trunk"]) add_natural_tree_instances( diff --git a/blender/osmassets/tree.py b/blender/osmassets/tree.py index caf4df8..dd8440b 100644 --- a/blender/osmassets/tree.py +++ b/blender/osmassets/tree.py @@ -95,8 +95,33 @@ def load_tree_variants(): for obj in imported: bpy.data.objects.remove(obj, do_unlink=True) - tris = sum(len(bm.loop_triangles) + len(lm.loop_triangles) - for bm, lm in variants) - print(f"Poly Haven tree variants loaded: {len(variants)} " - f"({tris} tris per instance)") - return variants +def assemble(positions, collection): + """Place island_tree_01 instances at `positions`. + + positions is a list of (x, y, height) tuples. Returns the number of + trees placed (0 when the model is unavailable). + """ + import math # noqa — tree.py has no top-level math import by design + + variants = load_tree_variants() + if not variants: + return 0 + + for index, (x, y, height) in enumerate(positions): + branch_mesh, leaf_mesh = variants[index % len(variants)] + target = max(4.0, height) + factor = target / 3.2 + + b_obj = bpy.data.objects.new(f"Tree_PH_{index:03d}_Branch", branch_mesh) + b_obj.location = (x, y, 0.0) + b_obj.scale = (factor, factor, factor) + b_obj.rotation_euler = (0, 0, (index * 1.61803398875) % 1.0 * math.tau) + collection.objects.link(b_obj) + + l_obj = bpy.data.objects.new(f"Tree_PH_{index:03d}_Leaf", leaf_mesh) + l_obj.location = (x, y, 0.0) + l_obj.scale = (factor, factor, factor) + l_obj.rotation_euler = (0, 0, (index * 1.61803398875) % 1.0 * math.tau) + collection.objects.link(l_obj) + + return len(positions)