Mushrooms: three varieties for the prep bench, plus gen-assets machine fixes
- button_mushroom / portobello / king_oyster in the ingredient cast: slippery skins (0.55-0.8, the tomato treatment), soft flesh, portobello gills layered and weeping; new 'mushroom' cap-and-stem silhouette. - Verified via harness: dinner knife pressed on a button skates (1 slip, cut lands 0.157 off-aim; tomato baseline 2 slips / 0.218), The Best Thing bites clean through under the same press, sawing properly cuts center with zero slips. - gen-assets.sh: find MODELBEAST at ~/MODELBEAST, token from backnforth/.env, MB_HOST to the m3ultra queue; every mb stage retries 10x with 60s pause because m4pro's venvs are gone (ponytail-marked, remove when m4pro is healed). - launch.json: port 5273 (5173 taken by another session's server). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
faf196657e
commit
ee1eb8ebc3
@ -4,8 +4,8 @@
|
||||
{
|
||||
"name": "toastsim",
|
||||
"runtimeExecutable": "npm",
|
||||
"runtimeArgs": ["run", "dev"],
|
||||
"port": 5173
|
||||
"runtimeArgs": ["run", "dev", "--", "--port", "5273"],
|
||||
"port": 5273
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
5
package-lock.json
generated
5
package-lock.json
generated
@ -1,13 +1,12 @@
|
||||
{
|
||||
"name": "toastsim",
|
||||
"version": "1.0.0",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "toastsim",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@dimforge/rapier3d-compat": "^0.19.3",
|
||||
"three": "^0.185.1"
|
||||
|
||||
BIN
public/assets/models/batard_loaf.glb
Normal file
BIN
public/assets/models/batard_loaf.glb
Normal file
Binary file not shown.
BIN
public/assets/models/cheese_hard.glb
Normal file
BIN
public/assets/models/cheese_hard.glb
Normal file
Binary file not shown.
BIN
public/assets/models/cheese_soft.glb
Normal file
BIN
public/assets/models/cheese_soft.glb
Normal file
Binary file not shown.
BIN
public/assets/models/cutting_board.glb
Normal file
BIN
public/assets/models/cutting_board.glb
Normal file
Binary file not shown.
BIN
public/assets/models/roast_tomatoes.glb
Normal file
BIN
public/assets/models/roast_tomatoes.glb
Normal file
Binary file not shown.
BIN
public/assets/models/sourdough_loaf.glb
Normal file
BIN
public/assets/models/sourdough_loaf.glb
Normal file
Binary file not shown.
BIN
public/assets/models/tomato_vine.glb
Normal file
BIN
public/assets/models/tomato_vine.glb
Normal file
Binary file not shown.
@ -9,6 +9,7 @@
|
||||
set -uo pipefail
|
||||
|
||||
MB_DIR="$HOME/Documents/MODELBEAST"
|
||||
[ -d "$MB_DIR" ] || MB_DIR="$HOME/MODELBEAST"
|
||||
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
OUT_MODELS="$REPO/public/assets/models"
|
||||
OUT_IMG="$REPO/public/assets/img"
|
||||
@ -16,17 +17,39 @@ mkdir -p "$OUT_MODELS" "$OUT_IMG"
|
||||
|
||||
cd "$MB_DIR" || exit 1
|
||||
# shellcheck disable=SC1091
|
||||
source data/agent.env
|
||||
if [ -f data/agent.env ]; then source data/agent.env
|
||||
else set -a; source "$HOME/Documents/backnforth/.env"; set +a; fi
|
||||
export MB_HOST="${MB_HOST:-http://100.89.131.57:8777}"
|
||||
|
||||
STYLE="chunky stylized claymation kitchen prop, soft matte plastic look, warm colors"
|
||||
SHOT="single object centered on plain light grey background, soft studio lighting, 3/4 view, chunky stylized game asset"
|
||||
|
||||
# ponytail: m4pro node has dead venvs (2026-07-17) — jobs routed there fail in ~1s,
|
||||
# so every stage retries up to 10x with a 60s pause until a healthy node takes it.
|
||||
# Remove the loops once m4pro is fixed or pulled from the pool.
|
||||
MB_TRIES=10 MB_PAUSE=60
|
||||
|
||||
# run_flux <seed> <prompt> [w] [h] -> asset id on stdout
|
||||
run_flux() {
|
||||
local seed="$1" prompt="$2" w="${3:-1024}" h="${4:-1024}"
|
||||
./mb run flux_local -p prompt="$prompt" -p model=flux2-klein-4b -p steps=4 \
|
||||
local seed="$1" prompt="$2" w="${3:-1024}" h="${4:-1024}" i out
|
||||
for i in $(seq 1 "$MB_TRIES"); do
|
||||
out=$(./mb run flux_local -p prompt="$prompt" -p model=flux2-klein-4b -p steps=4 \
|
||||
-p seed="$seed" -p width="$w" -p height="$h" --wait 2>/dev/null \
|
||||
| awk '/image/{print $1}' | tail -1
|
||||
| awk '/image/{print $1}' | tail -1)
|
||||
[ -n "$out" ] && { echo "$out"; return; }
|
||||
sleep "$MB_PAUSE"
|
||||
done
|
||||
}
|
||||
|
||||
# run_cutout <asset_id> -> asset id on stdout
|
||||
run_cutout() {
|
||||
local asset="$1" i out
|
||||
for i in $(seq 1 "$MB_TRIES"); do
|
||||
out=$(./mb run bg_remove_local --asset "$asset" -p resolution=2048 --wait 2>/dev/null \
|
||||
| awk '/image/{print $1}' | tail -1)
|
||||
[ -n "$out" ] && { echo "$out"; return; }
|
||||
sleep "$MB_PAUSE"
|
||||
done
|
||||
}
|
||||
|
||||
# gen_3d <name> <seed> <prompt> — each stage retries once (transient rsync/infra errors happen)
|
||||
@ -42,24 +65,21 @@ gen_3d() {
|
||||
fi
|
||||
[ -z "$img" ] && { echo " ! $name: flux failed twice"; return 1; }
|
||||
echo "→ [$name] cutout ($img)..."
|
||||
cut=$(./mb run bg_remove_local --asset "$img" -p resolution=2048 --wait 2>/dev/null | awk '/image/{print $1}' | tail -1)
|
||||
if [ -z "$cut" ]; then
|
||||
echo " ~ $name: bg_remove failed, retrying once..."
|
||||
cut=$(./mb run bg_remove_local --asset "$img" -p resolution=2048 --wait 2>/dev/null | awk '/image/{print $1}' | tail -1)
|
||||
fi
|
||||
[ -z "$cut" ] && { echo " ! $name: bg_remove failed twice"; return 1; }
|
||||
cut=$(run_cutout "$img")
|
||||
[ -z "$cut" ] && { echo " ! $name: bg_remove failed after $MB_TRIES tries"; return 1; }
|
||||
echo "→ [$name] mesh ($cut) — ~5 min..."
|
||||
local try glb
|
||||
for try in 1 2; do
|
||||
for try in $(seq 1 "$MB_TRIES"); do
|
||||
local tmp; tmp=$(mktemp -d)
|
||||
./mb run hunyuan3d_mlx --asset "$cut" -p octree_resolution=256 -p texture_size=1024 \
|
||||
-p max_num_view=6 --wait --download "$tmp" >/dev/null 2>&1
|
||||
glb=$(find "$tmp" -iname '*.glb' | head -1)
|
||||
if [ -n "$glb" ]; then mv "$glb" "$OUT_MODELS/$name.glb"; echo " ✓ $name.glb"; rm -rf "$tmp"; return 0; fi
|
||||
rm -rf "$tmp"
|
||||
[ "$try" = 1 ] && echo " ~ $name: no glb, retrying mesh once..."
|
||||
echo " ~ $name: no glb (try $try/$MB_TRIES), pausing ${MB_PAUSE}s..."
|
||||
sleep "$MB_PAUSE"
|
||||
done
|
||||
echo " ! $name: no glb after retry"
|
||||
echo " ! $name: no glb after $MB_TRIES tries"
|
||||
return 1
|
||||
}
|
||||
|
||||
@ -72,7 +92,7 @@ gen_2d() {
|
||||
[ -z "$img" ] && { echo " ! $name: flux failed"; return 1; }
|
||||
if [ "$cutout" = "cut" ]; then
|
||||
echo "→ [$name] cutout..."
|
||||
local c; c=$(./mb run bg_remove_local --asset "$img" -p resolution=2048 --wait 2>/dev/null | awk '/image/{print $1}' | tail -1)
|
||||
local c; c=$(run_cutout "$img")
|
||||
[ -n "$c" ] && img="$c"
|
||||
fi
|
||||
local tmp; tmp=$(mktemp -d)
|
||||
|
||||
@ -169,6 +169,25 @@ export class PrepView implements View {
|
||||
mesh.scale.set(1, 0.85, 1);
|
||||
break;
|
||||
}
|
||||
case 'mushroom': {
|
||||
// Cap on a stem; group extent stays ~size so the shared y-offset works.
|
||||
mesh = new THREE.Mesh(new THREE.SphereGeometry(r, 24, 16), skin);
|
||||
mesh.scale.set(1, 0.6, 1);
|
||||
mesh.position.y = ing.size * 0.15;
|
||||
const stemMat = new THREE.MeshStandardMaterial({
|
||||
color: new THREE.Color().setRGB(...ing.colors.flesh, THREE.SRGBColorSpace),
|
||||
roughness: 0.7,
|
||||
});
|
||||
const stem = new THREE.Mesh(
|
||||
new THREE.CylinderGeometry(r * 0.35, r * 0.42, ing.size * 0.6, 16),
|
||||
stemMat,
|
||||
);
|
||||
stem.position.y = -ing.size * 0.15;
|
||||
stem.castShadow = true;
|
||||
stem.receiveShadow = true;
|
||||
g.add(stem);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
mesh = new THREE.Mesh(new THREE.SphereGeometry(r, 28, 20), skin);
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
* 1 world unit ≈ 11cm, same convention as the loaf.
|
||||
*/
|
||||
|
||||
export type IngredientShape = 'sphere' | 'ovoid' | 'block' | 'wedge' | 'bulb';
|
||||
export type IngredientShape = 'sphere' | 'ovoid' | 'block' | 'wedge' | 'bulb' | 'mushroom';
|
||||
|
||||
export interface Ingredient {
|
||||
id: string;
|
||||
@ -39,7 +39,10 @@ export type IngredientId =
|
||||
| 'parmesan'
|
||||
| 'brie'
|
||||
| 'cucumber'
|
||||
| 'avocado';
|
||||
| 'avocado'
|
||||
| 'button_mushroom'
|
||||
| 'portobello'
|
||||
| 'king_oyster';
|
||||
|
||||
export const INGREDIENTS: Record<IngredientId, Ingredient> = {
|
||||
tomato: {
|
||||
@ -136,4 +139,39 @@ export const INGREDIENTS: Record<IngredientId, Ingredient> = {
|
||||
seeds: { count: 1, pocket: 'core' },
|
||||
colors: { skin: [0.16, 0.2, 0.1], flesh: [0.78, 0.85, 0.5] },
|
||||
},
|
||||
// The mushrooms: dry-slick skin that skates under a pressed blade, soft
|
||||
// flesh once the edge bites. Three varieties, three different fights.
|
||||
button_mushroom: {
|
||||
id: 'button_mushroom',
|
||||
name: 'button mushroom',
|
||||
shape: 'mushroom',
|
||||
size: 0.3,
|
||||
// Tiny and rolls away from the blade — the slip is the whole challenge.
|
||||
skin: { resistance: 0.15, slippery: 0.75 },
|
||||
flesh: { resistance: 0.15, moisture: 0.35 },
|
||||
roastable: true,
|
||||
colors: { skin: [0.92, 0.88, 0.8], flesh: [0.97, 0.95, 0.9] },
|
||||
},
|
||||
portobello: {
|
||||
id: 'portobello',
|
||||
name: 'portobello',
|
||||
shape: 'mushroom',
|
||||
size: 0.85,
|
||||
skin: { resistance: 0.2, slippery: 0.55 },
|
||||
// Gills crumble when mistreated, and it weeps dark juice.
|
||||
flesh: { resistance: 0.2, moisture: 0.45, layered: true },
|
||||
roastable: true,
|
||||
colors: { skin: [0.45, 0.32, 0.22], flesh: [0.82, 0.76, 0.66] },
|
||||
},
|
||||
king_oyster: {
|
||||
id: 'king_oyster',
|
||||
name: 'king oyster',
|
||||
shape: 'ovoid',
|
||||
size: 1.0,
|
||||
// Mostly one dense smooth stem — cuts like a slippery little log.
|
||||
skin: { resistance: 0.2, slippery: 0.8 },
|
||||
flesh: { resistance: 0.35, moisture: 0.3 },
|
||||
roastable: true,
|
||||
colors: { skin: [0.9, 0.87, 0.78], flesh: [0.96, 0.94, 0.88] },
|
||||
},
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user