Skip to content

Commit f90a3cf

Browse files
fix: rebuild trough, anvil, hand-pump, and signpost (#162)
* fix: rebuild water-trough as a staved vessel with water Solid U end-caps, a water fill, and an into-the-hollow camera so the piece no longer reads as an underside bench of slats. Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com> * fix: rebuild anvil as a London-pattern silhouette Stepped body, 16-seg horn, torus hoops, and a side-on camera so the piece reads as an anvil instead of a stack of dark boxes. Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com> * fix: rebuild hand-pump with a gooseneck and pump head Two-diameter column, quarter-arc spout, forked lever, and a stacked plinth so it no longer reads as a cone on a stick. Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com> * fix: rebuild signpost boards as painted planks Thin-Y planks, diamond tips, a collar cap, and regenerated gallery pages so the piece no longer reads as a stick with crayon arrows. Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com> --------- Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 4cb0e06 commit f90a3cf

22 files changed

Lines changed: 749 additions & 395 deletions

docs/gallery/anvil/index.html

Lines changed: 82 additions & 44 deletions
Large diffs are not rendered by default.
8.15 KB
Loading
792 Bytes
Loading
1.24 KB
Loading
-3 KB
Loading

docs/gallery/hand-pump/index.html

Lines changed: 135 additions & 60 deletions
Large diffs are not rendered by default.

docs/gallery/index.html

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,18 +1035,18 @@ <h2><a href="wheelbarrow/">wheelbarrow</a></h2>
10351035
<div class="card-body">
10361036
<h2><a href="anvil/">anvil</a></h2>
10371037
<p class="teaches">A procedural blacksmith anvil on a timber stump through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.</p>
1038-
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 1052 tris, two materials with 102 metal faces, UVs in 0..1 with zero AABB overlap, outer AABB 0.750×0.406×0.690 m, LOD ratios in band (5.2 COLLAPSE more aggressive on LOD2), convex collider 134 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.</p>
1038+
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 1696 tris, two materials with 274 metal faces, UVs in 0..1 with zero AABB overlap, outer AABB 0.746×0.410×0.682 m, LOD ratios in band (5.2 COLLAPSE more aggressive on LOD2), convex collider 162 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.</p>
10391039
<a class="card-link" href="anvil/">View example <span aria-hidden="true">&rarr;</span></a>
10401040
</div>
10411041
</article>
10421042
<article class="card" data-tags="mesh export showcase">
10431043
<a class="card-media" href="water-trough/" aria-label="water-trough example detail page">
1044-
<img src="assets/water-trough-hero.webp" alt="water-trough — A procedural staved water trough through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract." loading="lazy" decoding="async" />
1044+
<img src="assets/water-trough-hero.webp" alt="water-trough — A procedural staved water trough with water through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract." loading="lazy" decoding="async" />
10451045
</a>
10461046
<div class="card-body">
10471047
<h2><a href="water-trough/">water-trough</a></h2>
1048-
<p class="teaches">A procedural staved water trough through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.</p>
1049-
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 4008 tris, two materials with 168 metal faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.136×0.482×0.470 m, LOD ratios in band, convex collider 108 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.</p>
1048+
<p class="teaches">A procedural staved water trough with water through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.</p>
1049+
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 4776 tris, three materials with 168 metal and 60 water faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.162×0.528×0.488 m, LOD ratios in band, convex collider 128 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.</p>
10501050
<a class="card-link" href="water-trough/">View example <span aria-hidden="true">&rarr;</span></a>
10511051
</div>
10521052
</article>
@@ -1074,12 +1074,12 @@ <h2><a href="grindstone/">grindstone</a></h2>
10741074
</article>
10751075
<article class="card" data-tags="mesh export showcase">
10761076
<a class="card-media" href="hand-pump/" aria-label="hand-pump example detail page">
1077-
<img src="assets/hand-pump-hero.webp" alt="hand-pump — A procedural village hand pump through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract." loading="lazy" decoding="async" />
1077+
<img src="assets/hand-pump-hero.webp" alt="hand-pump — A procedural village hand pump with a gooseneck through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract." loading="lazy" decoding="async" />
10781078
</a>
10791079
<div class="card-body">
10801080
<h2><a href="hand-pump/">hand-pump</a></h2>
1081-
<p class="teaches">A procedural village hand pump through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.</p>
1082-
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 616 tris, two materials with 96 metal faces, UVs in 0..1 with zero AABB overlap, outer AABB 0.567×0.366×1.027 m, LOD ratios in band (5.2 COLLAPSE more aggressive on LOD2), convex collider 118 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.</p>
1081+
<p class="teaches">A procedural village hand pump with a gooseneck through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.</p>
1082+
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 1164 tris, two materials with 222 metal faces, UVs in 0..1 with zero AABB overlap, outer AABB 0.610×0.364×1.049 m, LOD ratios in band (5.2 COLLAPSE more aggressive on LOD2), convex collider 110 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.</p>
10831083
<a class="card-link" href="hand-pump/">View example <span aria-hidden="true">&rarr;</span></a>
10841084
</div>
10851085
</article>
@@ -1090,7 +1090,7 @@ <h2><a href="hand-pump/">hand-pump</a></h2>
10901090
<div class="card-body">
10911091
<h2><a href="signpost/">signpost</a></h2>
10921092
<p class="teaches">A procedural timber fingerboard signpost through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.</p>
1093-
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 388 tris, three materials with 66 metal and 22 board faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.162×0.147×1.575 m, LOD ratios in band (5.2 COLLAPSE more aggressive on LOD2), convex collider 92 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.</p>
1093+
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 504 tris, three materials with 66 metal and 24 board faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.368×0.201×1.566 m, LOD ratios in band (5.2 COLLAPSE more aggressive on LOD2), convex collider 56 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.</p>
10941094
<a class="card-link" href="signpost/">View example <span aria-hidden="true">&rarr;</span></a>
10951095
</div>
10961096
</article>

docs/gallery/signpost/index.html

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -253,18 +253,18 @@ <h1>signpost</h1>
253253
<img src="../assets/signpost-hero.webp" alt="signpost render" width="1280" height="720" />
254254
</button>
255255
<p class="zoom-hint">Rendered headless by the example itself — click to zoom.</p>
256-
<div class="callout"><span class="tag">witnesses</span> Recomputed: 388 tris, three materials with 66 metal and 22 board faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.162×0.147×1.575 m, LOD ratios in band (5.2 COLLAPSE more aggressive on LOD2), convex collider 92 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.</div>
256+
<div class="callout"><span class="tag">witnesses</span> Recomputed: 504 tris, three materials with 66 metal and 24 board faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.368×0.201×1.566 m, LOD ratios in band (5.2 COLLAPSE more aggressive on LOD2), convex collider 56 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.</div>
257257
<div class="runline">
258258
<pre id="runCmd">blender --background --python showcase/signpost/signpost.py --</pre>
259259
<button class="copy-btn" id="copyRun" type="button">Copy</button>
260260
</div>
261261
<section class="detail-section md">
262-
<p>A showcase piece, not an example. Procedural timber fingerboard signpost (square post, pyramidal cap, two painted boards, iron shoe and straps) then the shipped pipeline: unique-cell UVs, Cycles high-to-low normal bake, LOD chain, convex collider, Unity glTF export.</p>
262+
<p>A showcase piece, not an example. Procedural timber fingerboard signpost (square post, collar and pyramidal cap, two painted planks with diamond tips, iron shoe and straps) then the shipped pipeline: unique-cell UVs, Cycles high-to-low normal bake, LOD chain, convex collider, Unity glTF export.</p>
263263
<p>It asserts <strong>budget conformance</strong> of the generated result. It does not witness an API contract. &quot;It rendered without error&quot; is not a check.</p>
264264
<p><strong>Composes</strong> skills <code>mesh-editing-and-bmesh</code>, <code>bake-high-to-low</code>, <code>depsgraph-and-evaluated-data</code>, <code>engine-export-presets</code>, and snippets <code>bake_normal_high_to_low.py</code>, <code>setup_bake_target_image.py</code>, <code>lod_chain.py</code> / <code>decimate_to_budget.py</code>, <code>convex_hull_collider.py</code>, <code>export_preset_unity.py</code> (helpers copied, not imported as a package).</p>
265265
<h2>Budgets</h2>
266266
<p>Declared as named constants; every gate <strong>recomputes</strong> from the mesh, materials, UVs, evaluated LOD, collider, or export file.</p>
267-
<p>| Axis | Declared | Measured (4.5.11 / 5.1.2 / 5.2.1) | | --- | --- | --- | | Base triangles | 320–460 | 388 / 388 / 388 | | LOD1 ratio | 0.32–0.62 of base | 0.5000 / 0.5000 / 0.5000 | | LOD2 ratio | 0.10–0.35 of base | 0.2165 / 0.2165 / 0.1804 | | Materials | exactly 3 distinct, ≥24 metal and ≥12 board faces | 3 slots, 66 metal, 22 board | | UVs | in <code>0..1</code>, AABB overlap ≤ 1e-5 | in range, overlap 0 | | Outer AABB | (1.162, 0.147, 1.575) m ± 0.01 | (1.1620, 0.1474, 1.5750), zmin 0 | | Collider tris | ≤ 140 | 92 | | Export | written, size &gt; 0 | 40124 / 40124 / 40112 bytes |</p>
267+
<p>| Axis | Declared | Measured (4.5.11 / 5.1.2 / 5.2.1) | | --- | --- | --- | | Base triangles | 430–580 | 504 / 504 / 504 | | LOD1 ratio | 0.32–0.62 of base | 0.5000 / 0.5000 / 0.5000 | | LOD2 ratio | 0.10–0.35 of base | 0.2183 / 0.2183 / 0.1746 | | Materials | exactly 3 distinct, ≥24 metal and ≥12 board faces | 3 slots, 66 metal, 24 board | | UVs | in <code>0..1</code>, AABB overlap ≤ 1e-5 | in range, overlap 0 | | Outer AABB | (1.368, 0.201, 1.566) m ± 0.01 | (1.3679, 0.2014, 1.5660), zmin 0 | | Collider tris | ≤ 140 | 56 | | Export | written, size &gt; 0 | 45164 / 45164 / 45152 bytes |</p>
268268
<p>DECIMATE COLLAPSE triangle counts are <strong>not</strong> identical across series — 5.2.1 is more aggressive on LOD2. The gate is a ratio band, not an exact count. Bake pixels are stochastic; the gate is <code>has_data</code> plus operator <code>FINISHED</code>, not byte-identity. Construction uses no RNG. Export byte counts differ by 12 B on 5.2.1 (glTF serializer), not a gated axis.</p>
269269
<p><code>--skip-decimate</code> skips the LOD DECIMATE stage so LOD1 ratio is 1.0 and exit 9 fires. That is the named budget the falsifier violates.</p>
270270
<h2>Run</h2>
@@ -319,20 +319,20 @@ <h2>Source</h2>
319319
sys.dont_write_bytecode = <span class="k">True</span>
320320
<span class="k">import</span> gallery_framing <span class="c"># noqa: E402</span>
321321

322-
POST_W = <span class="n">0.110</span>
322+
POST_W = <span class="n">0.118</span>
323323
POST_H = <span class="n">1.48</span>
324-
CAP_H = <span class="n">0.095</span>
324+
CAP_H = <span class="n">0.058</span>
325325
SHOE_H = <span class="n">0.048</span>
326326
SHOE_SCALE = <span class="n">1.34</span>
327-
BOARD_Y = <span class="n">0.072</span>
328-
BOARD_ZTH = <span class="n">0.046</span>
329-
BOARD_A = (<span class="n">1.24</span>, <span class="n">0.52</span>, <span class="n">1.0</span>)
330-
BOARD_B = (<span class="n">1.02</span>, <span class="n">0.44</span>, -<span class="n">1.0</span>)
327+
BOARD_T = <span class="n">0.028</span>
328+
BOARD_H = <span class="n">0.112</span>
329+
BOARD_A = (<span class="n">1.24</span>, <span class="n">0.62</span>, <span class="n">1.0</span>, <span class="n">0.12</span>)
330+
BOARD_B = (<span class="n">1.00</span>, <span class="n">0.54</span>, -<span class="n">1.0</span>, -<span class="n">0.18</span>)
331331

332332
BBOX_TOL = <span class="n">0.01</span>
333-
OUTER_SIZE = (<span class="n">1.162</span>, <span class="n">0.147</span>, <span class="n">1.575</span>)
334-
BASE_TRIS_MIN = <span class="n">320</span>
335-
BASE_TRIS_MAX = <span class="n">460</span>
333+
OUTER_SIZE = (<span class="n">1.368</span>, <span class="n">0.201</span>, <span class="n">1.566</span>)
334+
BASE_TRIS_MIN = <span class="n">430</span>
335+
BASE_TRIS_MAX = <span class="n">580</span>
336336
LOD1_RATIO_MIN = <span class="n">0.32</span>
337337
LOD1_RATIO_MAX = <span class="n">0.62</span>
338338
LOD2_RATIO_MIN = <span class="n">0.10</span>
@@ -559,12 +559,20 @@ <h2>Source</h2>
559559
WOOD_IDX,
560560
)
561561
)
562+
wood.extend(
563+
add_box(
564+
bm,
565+
(<span class="n">0.0</span>, <span class="n">0.0</span>, POST_H + <span class="n">0.014</span>),
566+
(POST_W * <span class="n">1.16</span>, POST_W * <span class="n">1.16</span>, <span class="n">0.028</span>),
567+
WOOD_IDX,
568+
)
569+
)
562570
wood.extend(
563571
add_cone(
564572
bm,
565-
(<span class="n">0.0</span>, <span class="n">0.0</span>, POST_H + CAP_H / <span class="n">2.0</span>),
566-
POST_W * <span class="n">0.78</span>,
567-
<span class="n">0.012</span>,
573+
(<span class="n">0.0</span>, <span class="n">0.0</span>, POST_H + <span class="n">0.028</span> + CAP_H / <span class="n">2.0</span>),
574+
POST_W * <span class="n">0.72</span>,
575+
<span class="n">0.008</span>,
568576
CAP_H,
569577
<span class="n">4</span>,
570578
WOOD_IDX,
@@ -586,50 +594,53 @@ <h2>Source</h2>
586594
<span class="k">for</span> f <span class="k">in</span> ret.get(<span class="s">&quot;faces&quot;</span>) <span class="k">or</span> []:
587595
f.material_index = WOOD_IDX
588596

589-
<span class="k">for</span> z, length, sign <span class="k">in</span> (BOARD_A, BOARD_B):
590-
cx = sign * (half + length / <span class="n">2.0</span> - <span class="n">0.018</span>)
597+
<span class="k">for</span> z, length, sign, yaw <span class="k">in</span> (BOARD_A, BOARD_B):
598+
eul = Euler((<span class="n">0.0</span>, <span class="n">0.0</span>, yaw))
599+
rot = eul.to_matrix()
600+
inner = Vector((sign * (half - <span class="n">0.016</span>), <span class="n">0.0</span>, z))
601+
center = inner + rot @ Vector((sign * length / <span class="n">2.0</span>, <span class="n">0.0</span>, <span class="n">0.0</span>))
591602
boards.extend(
592603
add_box(
593604
bm,
594-
(cx, <span class="n">0.0</span>, z),
595-
(length, BOARD_Y, BOARD_ZTH),
605+
(center.x, center.y, center.z),
606+
(length, BOARD_T, BOARD_H),
596607
BOARD_IDX,
608+
euler=(<span class="n">0.0</span>, <span class="n">0.0</span>, yaw),
597609
)
598610
)
599-
tip_x = cx + sign * (length / <span class="n">2.0</span> + <span class="n">0.028</span>)
611+
tip = inner + rot @ Vector((sign * (length + <span class="n">0.004</span>), <span class="n">0.0</span>, <span class="n">0.0</span>))
600612
boards.extend(
601-
add_cone(
613+
add_box(
602614
bm,
603-
(tip_x, <span class="n">0.0</span>, z),
604-
<span class="n">0.052</span>,
605-
<span class="n">0.004</span>,
606-
<span class="n">0.072</span>,
607-
<span class="n">3</span>,
615+
(tip.x, tip.y, tip.z),
616+
(<span class="n">0.088</span>, BOARD_T, <span class="n">0.088</span>),
608617
BOARD_IDX,
609-
euler=(<span class="n">0.0</span>, sign * math.pi / <span class="n">2.0</span>, <span class="n">0.0</span>),
618+
euler=(<span class="n">0.0</span>, math.pi / <span class="n">4.0</span>, yaw),
610619
)
611620
)
621+
t = <span class="n">0.012</span>
622+
h = BOARD_H + <span class="n">0.024</span>
612623
metal.extend(
613624
add_box(
614625
bm,
615-
(sign * (half + <span class="n">0.010</span>), <span class="n">0.0</span>, z),
616-
(<span class="n">0.020</span>, BOARD_Y + <span class="n">0.016</span>, BOARD_ZTH + <span class="n">0.018</span>),
626+
(sign * (half + t / <span class="n">2.0</span>), <span class="n">0.0</span>, z),
627+
(t, POST_W * <span class="n">0.94</span>, h),
617628
METAL_IDX,
618629
)
619630
)
620631
metal.extend(
621632
add_box(
622633
bm,
623-
(<span class="n">0.0</span>, half + <span class="n">0.010</span>, z),
624-
(POST_W * <span class="n">0.92</span>, <span class="n">0.014</span>, BOARD_ZTH * <span class="n">1.15</span>),
634+
(<span class="n">0.0</span>, half + t / <span class="n">2.0</span>, z),
635+
(POST_W * <span class="n">0.94</span>, t, h),
625636
METAL_IDX,
626637
)
627638
)
628639
metal.extend(
629640
add_box(
630641
bm,
631-
(<span class="n">0.0</span>, -(half + <span class="n">0.010</span>), z),
632-
(POST_W * <span class="n">0.92</span>, <span class="n">0.014</span>, BOARD_ZTH * <span class="n">1.15</span>),
642+
(<span class="n">0.0</span>, -(half + t / <span class="n">2.0</span>), z),
643+
(POST_W * <span class="n">0.94</span>, t, h),
633644
METAL_IDX,
634645
)
635646
)
@@ -817,7 +828,7 @@ <h2>Source</h2>
817828
low = build_signpost_mesh(<span class="s">&quot;SignpostLow&quot;</span>, bevel_offset=<span class="n">0.004</span>, bevel_segments=<span class="n">2</span>)
818829
high = build_signpost_mesh(<span class="s">&quot;SignpostHigh&quot;</span>, bevel_offset=<span class="n">0.004</span>, bevel_segments=<span class="n">4</span>)
819830
wood = principled(<span class="s">&quot;SignpostWood&quot;</span>, (<span class="n">0.34</span>, <span class="n">0.18</span>, <span class="n">0.07</span>, <span class="n">1.0</span>), <span class="n">0.0</span>, <span class="n">0.62</span>)
820-
board = principled(<span class="s">&quot;SignpostBoard&quot;</span>, (<span class="n">0.72</span>, <span class="n">0.58</span>, <span class="n">0.28</span>, <span class="n">1.0</span>), <span class="n">0.0</span>, <span class="n">0.55</span>)
831+
board = principled(<span class="s">&quot;SignpostBoard&quot;</span>, (<span class="n">0.76</span>, <span class="n">0.58</span>, <span class="n">0.22</span>, <span class="n">1.0</span>), <span class="n">0.0</span>, <span class="n">0.52</span>)
821832
metal = principled(<span class="s">&quot;SignpostIron&quot;</span>, (<span class="n">0.14</span>, <span class="n">0.145</span>, <span class="n">0.155</span>, <span class="n">1.0</span>), <span class="n">1.0</span>, <span class="n">0.38</span>)
822833
assign_slots(low, wood, board, metal)
823834
assign_slots(high, wood, board, metal)
@@ -974,7 +985,7 @@ <h2>Source</h2>
974985
ob.hide_render = <span class="k">True</span>
975986
ob.hide_viewport = <span class="k">True</span>
976987

977-
low.rotation_euler.z = math.radians(-<span class="n">18.0</span>)
988+
low.rotation_euler.z = math.radians(-<span class="n">12.0</span>)
978989
low.rotation_euler.x = math.radians(<span class="n">0.0</span>)
979990

980991
floor_me = bpy.data.meshes.new(<span class="s">&quot;Floor&quot;</span>)
@@ -1021,10 +1032,10 @@ <h2>Source</h2>
10211032
cam_data = bpy.data.cameras.new(<span class="s">&quot;Cam&quot;</span>)
10221033
cam_data.lens = <span class="n">50.0</span>
10231034
cam = bpy.data.objects.new(<span class="s">&quot;Cam&quot;</span>, cam_data)
1024-
cam.location = (<span class="n">3.06</span>, -<span class="n">4.02</span>, <span class="n">1.38</span>)
1035+
cam.location = (<span class="n">2.80</span>, -<span class="n">3.40</span>, <span class="n">1.35</span>)
10251036
scene.collection.objects.link(cam)
10261037
aim = bpy.data.objects.new(<span class="s">&quot;Aim&quot;</span>, <span class="k">None</span>)
1027-
aim.location = (<span class="n">0.0</span>, <span class="n">0.0</span>, <span class="n">0.78</span>)
1038+
aim.location = (<span class="n">0.0</span>, <span class="n">0.0</span>, <span class="n">0.82</span>)
10281039
scene.collection.objects.link(aim)
10291040
con = cam.constraints.new(<span class="s">&quot;TRACK_TO&quot;</span>)
10301041
con.target = aim

0 commit comments

Comments
 (0)