Factory function to create Harvest Tree in your world.

export function createAsset(THREE, options = {}) {
  const root = new THREE.Group();
  root.name = options.name ?? "Harvest Tree";
  root.userData = { assetRole: "nature", generatedBy: 'public asset batch' };
  const cache = new Map();
  function mat(def) {
    const key = [def.color, def.opacity ?? 1, def.metalness ?? 0, def.roughness ?? 0.72, def.emissive ?? '', def.emissiveIntensity ?? 0].join('|');
    if (cache.has(key)) return cache.get(key);
    const material = new THREE.MeshStandardMaterial({ color: def.color, roughness: def.roughness ?? 0.72, metalness: def.metalness ?? 0, opacity: def.opacity ?? 1, transparent: (def.opacity ?? 1) < 1, emissive: def.emissive ?? '#000000', emissiveIntensity: def.emissiveIntensity ?? 0 });
    cache.set(key, material);
    return material;
  }
  const defs = [{"id":"ground_shadow","name":"Ground Shadow","position":[0,0.03,0],"boxes":[{"name":"shadow","size":[2.3,0.04,1.7],"position":[0,0,0],"color":"#6b7280","opacity":0.28}]},{"id":"trunk","name":"Tree Trunk","position":[0,0.78,0],"boxes":[{"name":"lower","size":[0.48,1.15,0.48],"position":[0,0,0],"color":"#7a4a25"},{"name":"upper","size":[0.38,0.75,0.38],"position":[0,0.7,0],"color":"#8b5a2b"}]},{"id":"leaf_cluster","name":"Leaf Cluster","position":[0,2.15,0],"boxes":[{"name":"core","size":[1.75,1,1.55],"position":[0,0,0],"color":"#65a832"},{"name":"top","size":[1.25,0.58,1.15],"position":[0,0.62,0],"color":"#7cc44b"},{"name":"left","size":[0.9,0.72,1.05],"position":[-0.72,0.05,0],"color":"#5c9d2e"},{"name":"right","size":[0.9,0.72,1.05],"position":[0.72,0.05,0],"color":"#6fb83d"},{"name":"front","size":[1.1,0.72,0.75],"position":[0,0.02,0.62],"color":"#76bd45"}]},{"id":"fruit_group","name":"Fruit Group","position":[0,2.22,0.72],"boxes":[{"name":"apple L","size":[0.22,0.22,0.22],"position":[-0.55,0.12,0],"color":"#ef4444"},{"name":"apple C","size":[0.24,0.24,0.24],"position":[0.05,-0.18,0.03],"color":"#f97316"},{"name":"apple R","size":[0.22,0.22,0.22],"position":[0.56,0.1,0],"color":"#ef4444"}],"parent":"leaf_cluster"},{"id":"falling_fruit","name":"Falling Fruit","position":[0.48,1.55,0.8],"boxes":[{"name":"apple","size":[0.26,0.26,0.26],"position":[0,0,0],"color":"#ef4444"},{"name":"leaf","size":[0.12,0.06,0.1],"position":[0.08,0.18,0],"color":"#22c55e"}]}];
  const groups = new Map();
  for (const def of defs) {
    const group = new THREE.Group();
    group.name = def.name;
    group.position.set(def.position[0], def.position[1], def.position[2]);
    if (def.rotation) group.rotation.set(def.rotation[0], def.rotation[1], def.rotation[2]);
    group.userData.partId = def.id;
    group.userData.editable = true;
    group.userData.selection = { id: def.id, kind: 'asset', label: def.name };
    for (const item of def.boxes) {
      const mesh = new THREE.Mesh(new THREE.BoxGeometry(item.size[0], item.size[1], item.size[2]), mat(item));
      mesh.name = item.name;
      mesh.position.set(item.position[0], item.position[1], item.position[2]);
      if (item.rotation) mesh.rotation.set(item.rotation[0], item.rotation[1], item.rotation[2]);
      mesh.castShadow = true;
      mesh.receiveShadow = true;
      group.add(mesh);
    }
    groups.set(def.id, group);
  }
  for (const def of defs) (def.parent ? groups.get(def.parent) : root).add(groups.get(def.id));
  const scale = Number(options.scale ?? 1);
  root.scale.setScalar(Number.isFinite(scale) ? scale : 1);
  return root;
}