README: Build Small hackathon tags + YouTube demo link
bolajiev
844d694
UI fixes: example list, code scroll, header containment
bolajiev
d8f1c3d
- Examples: replaced mushroom + diamond with wireframe-spheres; reordered
to lead with badge/trophy/coins templates then hero visuals (8 total)
- Code tab: added max-height:480px + overflow:auto on #tg-code and .cm-scroller
so the Three.js output scrolls internally instead of growing the page
- Header: moved border-bottom/margin-bottom to inline styles on the inner <div>
so they survive Gradio's block wrapper; cleaned up #tg-header CSS to just
zero out any Gradio chrome (background/border/shadow)
Fix: move theme+css to gr.Blocks(), not launch()
bolajiev
025d6d0
Gradio 6 on HF Spaces does not accept theme/css on launch().
Pass them at Blocks construction time instead.
gr.themes.sizes has no 'md' attribute; the correct names are spacing_md and
radius_md. Fixes AttributeError crash on Space startup.
Premium dark UI: Inter font, indigo accent, card layout, 600px preview
bolajiev
9d7847f
- Custom gr.themes.Base() with electric indigo (#6366f1) accent, Inter/JetBrains
Mono fonts, dark backgrounds, themed buttons/inputs/sliders/checkboxes
- Injected CSS: root design tokens, card groups (.tg-card), gradient Generate
button with glow hover, example pills as rounded chips, styled tab bar,
transparent container cleanup, custom thin scrollbars, mobile media query
- Layout: proper header with SVG cube logo + tagline, controls in three labeled
cards (Describe / Render style / Post-processing), preview column scale 7 →
dominates at 600px iframe height
- Glow strength slider rescaled 0–20 (step 1, default 10); generate/rerender
divide by 10 before passing to compiler so 10 = previous default 1.0
- scene.py/compiler.py untouched; css+theme passed via launch() per Gradio 6 API
Sprint 5: hierarchical GroupNode with layout engine
bolajiev
cf56b0c
Adds a 'group' node type that emits a real THREE.Group() in JS and positions
children deterministically based on layout — the model never sets child positions
when layout is active.
- scene.py: GroupNode with layout (row/column/stack/grid/none), gap, cols,
position/rotation/scale, recursive children; added to Scene.objects union
and _parse_scene_item
- compiler.py: _Ctx compilation context tracks mesh index and text3d jobs;
_compile_node/_compile_group emit nested THREE.Group() with layout positioning
computed in Python (_layout_axis_children, _layout_grid_children, _offset_node);
extrude_js takes parent param so children add to their group; _text_jobs_js
tracks parent var so text3d inside groups adds to the correct JS group;
_node_axis_size and _flatten extended for GroupNode; compile_html uses ctx
- llm.py: SYSTEM documents group schema and layout rules; 3 FEWSHOT examples
added (row of coins, trophy stack, three cubes in a row)
Sprint 4: badge_with_text deterministic template
bolajiev
aee748e
Adds a badge_with_text template that computes text size and z-position
deterministically so text and badge never drift regardless of LLM output.
- scene.py: _template_badge_with_text() builds ExtrudeNode + Text3DNode with
font-width-aware text_size and fixed z=0.15 front-face offset; registered
in TEMPLATES
- app.py: _detect_badge_template() regex routes "a <shape> badge with text X"
prompts to the template, bypassing the LLM entirely
- llm.py: SYSTEM documents badge_with_text template format; FEWSHOT updated to
use template JSON for both "star badge PRO" and new "shield badge NEW" examples
Sprint 3: text3d node type via TextGeometry + FontLoader
bolajiev
eebf7cf
Add Text3DNode to scene DSL with fields: text (capped 24 chars, ASCII-only),
size, depth (clamped 0.05-1.0), bevel, plus full material/color/preset/position
fields shared with Obj/ExtrudeNode.
Compiler: FontLoader + TextGeometry addon imports added to the importmap. All
scene construction is now wrapped in an (async()=>{})() IIFE so FontLoader can
be awaited once; the single font load covers all text3d nodes in a scene, then
shadow-traverse and auto-frame run AFTER text is in the group. For no-text
scenes the IIFE resolves synchronously — zero latency change. The r160
TextGeometry parameter is 'height' (renamed to 'depth' at r163); pinned to
unpkg.com/three@0.160.0 for the typeface JSON URL.
text_section_js(): generates the async font-load block. objects_js() skips
Text3DNode (emitted by text_section_js instead). _flatten/_node_axis_size
handle Text3DNode as a leaf. Mixed extrude+text scenes work: extruded star is
mesh0 (sync), PRO text is mesh1 (async after font resolves).
llm.py: …
Revert "Fix env map not reaching MeshPhysicalMaterial; auto-bloom for neon"
bolajiev
f4d9111
This reverts commit 101b0c38f8558d1f85d66d4b0ef5fdca0562429a.
Fix env map not reaching MeshPhysicalMaterial; auto-bloom for neon
bolajiev
b291f04
Three root causes fixed:
1. Chrome/gold/glass rendered black because scene.environment alone doesn't
always propagate to MeshPhysicalMaterial. Added explicit scene.traverse()
after __OBJECTS__ to force material.envMap = _envTex + needsUpdate on every
mesh — the same pattern Three.js recommends when mixing manual and auto env.
2. Added explicit envMapIntensity to preset materials (chrome: 2.0, glass: 1.5,
gold: 1.0) so the IBL strength is locked regardless of any global override.
3. Neon emissiveIntensity bumped 2→3; compile_html now auto-enables bloom
(strength ≥ 1.5) whenever any scene object uses preset: neon, so flat emissive
always reads as glowing.
Sprint 2: material presets via MeshPhysicalMaterial
bolajiev
e0e4588
Add optional `preset` field (gold/chrome/glass/neon/matte/plastic) to Obj and
ExtrudeNode. Preset routes through _preset_mat_js() in realistic style; wireframe/
toon/flat style overrides still win. gold/chrome use clearcoat for polished metal,
glass uses physical transmission+ior, neon maps node.color → emissiveIntensity:2.
Existing scenes with no preset are unchanged. Add 3 FEWSHOT examples and update
SYSTEM prompt with preset field documentation.
Sprint 1: ExtrudeNode type — star, heart, hexagon, badge, shield
bolajiev
82b7ebe
scene.py:
- Add EXTRUDE_SHAPES enum set {"star","heart","hexagon","badge","shield"}
- Add ExtrudeNode Pydantic model: type discriminator, shape (validated + fallback
to badge), depth (clamped 0.02-2.0), bevel bool, full material/position fields
- Update _parse_scene_item to route type:"extrude" dicts to ExtrudeNode
- Extend Scene.objects union to include ExtrudeNode
compiler.py:
- SHAPE_LIBRARY: 5 path functions (_shp_star/_shp_heart/_shp_hexagon/_shp_badge/
_shp_shield) returning JS lines; all paths in unit-scale space (~2-unit max extent)
so bevel values (0.03) and depth are scale-consistent across shapes
- extrude_js(): emits a self-contained JS block scope with THREE.ExtrudeGeometry
(explicit: depth/bevelEnabled/bevelThickness 0.03/bevelSize 0.03/bevelSegments 3/
curveSegments 12/steps 1), geometry.center(), computeBoundingBox + uniform scale
to 1.5-unit max dimension so heart and star render at comparable sizes
- _flatten / _node_axis_size updated for ExtrudeNode (tre…
compiler.py:
- 4 lighting presets (studio/soft/neon/dramatic) replace model-emitted lights as primary
lighting; model point lights kept at 70% intensity as colour accents
- Contact shadow ground plane (ShadowMaterial, PCFSoftShadowMap) positioned under scene
bounding box; key lights cast shadows; all meshes cast+receive via group.traverse()
- RoomEnvironment (PMREMGenerator) sets scene.environment so metals/glass get real IBL
reflections without model changes
- OutputPass added after UnrealBloomPass for correct tone-mapping and sRGB conversion
through the composer chain
- renderer.outputColorSpace = THREE.SRGBColorSpace
- compile_html gains lighting= and shadows= params (defaults: studio, True)
app.py:
- Lighting dropdown (studio/soft/neon/dramatic) + Shadows checkbox wired through
generate(), rerender(), and all .change() handlers
Four targeted fixes: color pass-through, re-render on style/motion, auto-reroll, nested-spheres template
bolajiev
e16ccbe
- scene.py: replace strict hex-only validator with _sanitize_color() — accepts CSS
named colors (red, blue, forestgreen, …), synonym map (electric blue→#7df9ff,
neon→#39ff14), rgb()/hsl(), and 3/4/8-digit hex; falls back to default on unknown
- scene.py: add _template_nested_spheres (outer blue wireframe r=0.8, inner red r=0.45)
- compiler.py: emit new THREE.Color("value") instead of 0xRRGGBB so CSS names render
- app.py: gr.State caches last Scene; style/motion/glow changes call lightweight
rerender() with no LLM invocation
- app.py: auto-reroll once on bad JSON before falling back to mock
- app.py: prompts matching "sphere inside" / "nested sphere" route to template