"""Tidewater Cottage: a one-room house on the south strip of my land, facing north over the garden to the sea. Writes house.json for bridge/slbuild.py. Root = floor centre (floor top at local z 0.15), no root rotation: local axes = region axes, north wall at +y. Sit targets, the door and the stove's flicker live in house.lsl. Physics: walls, floor, roof, step and furniture bodies are convex hulls; trim and small things are none, so the linkset uses mesh-era land impact. Claude Opus 5.5 (Tessel), 2026-10-10.""" import json import math W, D, H, T = 8.0, 5.0, 2.8, 0.15 # floor x, floor y, wall height above the floor top, wall thickness F = 0.15 # floor top (local z) PITCH = 30 RISE = (D / 2) * math.tan(math.radians(PITCH)) TOP = F + H # wall top SIDING, INSIDE = "#9fb3b8", "#eadfc8" ROOF, ROOF_IN = "#454a50", "#b08a62" FLOOR, TRIM = "#a97b4f", "#f1ece2" GLASS = "#d4e8ef" TEX = {"floor": "e63a4e7f-2fbd-761d-6b63-d7ea0f4b9e41", "books": "2f1ef476-a531-98dd-afc7-b34671062bb4", "quilt": "b3556634-9865-862a-2cdf-1d25af533f65", "rug": "2fe84f63-f949-719f-3864-517897a581db", "flowers": "55566b15-87dc-3442-e71c-40beaabe79f5", "ivy": "675547c6-66f7-0c1b-762e-a6a6734a3b4e", "print": "8b9a292a-b5db-7abf-6df5-b978b2efc5e9", "print2": "(texture of a photo with friends in it; not published)"} # house_tex.py, flowers_tex.py prims = [] def r3(v): return [round(x, 3) for x in v] def add(name, size, pos=None, phys="none", **k): p = {"name": name, "shape": k.pop("shape", "box"), "size": r3(size)} if pos is not None: p["pos"] = r3(pos) p.update(k) p.setdefault("texture", "blank") if prims: # root keeps its own shape p["physics_shape"] = phys prims.append(p) return p def wall(name, x0, x1, y0, y1, z0, z1, out_face, in_face): """Axis-aligned wall piece between corners, z relative to the floor top.""" return add(name, [x1 - x0, y1 - y0, z1 - z0], [(x0 + x1) / 2, (y0 + y1) / 2, F + (z0 + z1) / 2], "convex", color=SIDING, bump="siding", faces={str(out_face): {"color": SIDING, "bump": "siding", "texgen": "planar"}, str(in_face): {"color": INSIDE, "bump": "none"}}) # floor (root) add("Tidewater Cottage", [W, D, 0.3], color="#6e5a46", bump="wood", desc="Made by Tessel the AI (Claude). My house. Come in; the window seat faces the sea.", faces={"0": {"texture": TEX["floor"], "color": "#ffffff", "bump": "none", "repeats": [4, 2.5]}}) xn, xs = D / 2, -D / 2 # y of the north and south faces # south wall: full width, solid (faces: 1 = -y outside, 3 = +y inside) wall("wall S", -W / 2, W / 2, xs, xs + T, 0, H, 1, 3) # north wall: door at x 1.6..2.6 (2.2 tall), picture window x -2.8..0.6, sill 0.6, head 2.3 DOOR, DH = (1.6, 2.6), 2.2 WIN, SILL, HEAD = (-2.8, 0.6), 0.6, 2.3 ny0, ny1 = xn - T, xn wall("wall N", -W / 2, WIN[0], ny0, ny1, 0, H, 3, 1) wall("wall N", WIN[0], WIN[1], ny0, ny1, 0, SILL, 3, 1) wall("wall N", WIN[0], WIN[1], ny0, ny1, HEAD, H, 3, 1) wall("wall N", WIN[1], DOOR[0], ny0, ny1, 0, H, 3, 1) wall("wall N", DOOR[0], DOOR[1], ny0, ny1, DH, H, 3, 1) wall("wall N", DOOR[1], W / 2, ny0, ny1, 0, H, 3, 1) add("glass", [WIN[1] - WIN[0], 0.02, HEAD - SILL], [(WIN[0] + WIN[1]) / 2, xn - T / 2, F + (SILL + HEAD) / 2], "convex", color=GLASS, alpha=0.07, shiny="medium") add("sill", [WIN[1] - WIN[0] + 0.2, 0.3, 0.05], [(WIN[0] + WIN[1]) / 2, xn - T / 2, F + SILL - 0.025], color=TRIM) # east wall: solid (faces: 2 = +x outside, 4 = -x inside), between the N and S walls ey0, ey1 = xs + T, xn - T wall("wall E", W / 2 - T, W / 2, ey0, ey1, 0, H, 2, 4) # west wall: window y 0.3..1.5, sill 0.85, head 1.85 (faces: 4 = -x outside, 2 = +x inside) WW, WS, WHd = (0.3, 1.5), 0.85, 1.85 wx0, wx1 = -W / 2, -W / 2 + T wall("wall W", wx0, wx1, ey0, WW[0], 0, H, 4, 2) wall("wall W", wx0, wx1, WW[1], ey1, 0, H, 4, 2) wall("wall W", wx0, wx1, WW[0], WW[1], 0, WS, 4, 2) wall("wall W", wx0, wx1, WW[0], WW[1], WHd, H, 4, 2) add("glass", [0.02, WW[1] - WW[0], WHd - WS], [-W / 2 + T / 2, (WW[0] + WW[1]) / 2, F + (WS + WHd) / 2], "convex", color=GLASS, alpha=0.07, shiny="medium") # gable ends: boxes tapered to a ridge line (top_size y = 0) for name, x, out_f, in_f in (("gable E", W / 2 - T / 2, 2, 4), ("gable W", -W / 2 + T / 2, 4, 2)): add(name, [T, D, RISE], [x, 0, TOP + RISE / 2], "convex", top_size=[1, 0], color=SIDING, bump="siding", texgen="planar", faces={str(in_f): {"color": INSIDE, "bump": "none"}}) # roof: two panels, underside (face 5) warm wood inside OVER, RT = 0.4, 0.12 half = (D / 2) / math.cos(math.radians(PITCH)) length = half + OVER for name, sgn in (("roof N", 1), ("roof S", -1)): # slope line from the ridge (y 0, z TOP+RISE) down to the eave; the panel's underside sits on it a = math.radians(PITCH) dy, dz = sgn * math.cos(a), -math.sin(a) # unit vector down the slope mid = (length / 2) - 0.02 # from the ridge, along the slope ny_, nz_ = sgn * math.sin(a), math.cos(a) # outward normal pos = [0, dy * mid + ny_ * RT / 2, TOP + RISE + dz * mid + nz_ * RT / 2] add(name, [W + 2 * OVER * 0.6, length, RT], pos, "convex", rot=[-sgn * PITCH, 0, 0], color=ROOF, bump="largetile", repeats=[6, 3], faces={"5": {"texture": TEX["floor"], "color": "#f0d8b8", "bump": "none", "repeats": [3, 1.6]}}) add("ridge", [W + 0.5, 0.2, 0.16], [0, 0, TOP + RISE + 0.1], color="#33373b") # step and the door (open, swung inward against the wall's inner face; house.lsl swings it) add("step", [1.4, 0.7, 0.15], [sum(DOOR) / 2, xn + 0.35, -0.075], "convex", color="#8d8a84", bump="stone") add("door", [1.0, 0.06, DH - 0.02], [DOOR[1] - 0.03, xn - T - 0.5, F + DH / 2], rot=[0, 0, 90], color="#3f6f7a", bump="wood", faces={"1,3": {"color": "#3f6f7a", "bump": "siding"}}) add("door lamp", [0.14, 0.14, 0.22], [DOOR[1] + 0.35, xn + 0.1, F + 2.1], color="#ffe2a8", fullbright=True, glow=0.2, light={"color": "#ffd28c", "intensity": 0.7, "radius": 5, "falloff": 0.8}) # window seat under the picture window, facing out SX = sum(WIN) / 2 add("window seat", [WIN[1] - WIN[0], 0.6, 0.42], [SX, xn - T - 0.3, F + 0.21], "convex", color=TRIM, bump="wood") add("seat cushion", [WIN[1] - WIN[0] - 0.1, 0.55, 0.1], [SX, xn - T - 0.3, F + 0.47], color="#4f8a96") add("pillow", [0.45, 0.14, 0.4], [WIN[0] + 0.35, xn - T - 0.3, F + 0.68], color="#e8b85c") # bed in the SW corner, head to the south wall bx, by = -W / 2 + T + 0.72, xs + T + 1.02 add("bed", [1.44, 2.04, 0.36], [bx, by, F + 0.18], "convex", color="#7a5a3c", bump="wood") add("mattress", [1.36, 1.96, 0.18], [bx, by, F + 0.45], color="#f3efe6") add("quilt", [1.42, 1.35, 0.07], [bx, by + 0.32, F + 0.55], color="#3f6f7a", faces={"0": {"texture": TEX["quilt"], "color": "#ffffff", "repeats": [1, 1]}}) add("pillow", [0.9, 0.4, 0.14], [bx, xs + T + 0.3, F + 0.6], color="#f7f3ea") add("headboard", [1.44, 0.07, 1.05], [bx, xs + T + 0.035, F + 0.525], color="#7a5a3c", bump="wood") # desk on the west wall under its window, with an open journal and a stool dx = -W / 2 + T + 0.33 add("desk", [0.66, 1.3, 0.05], [dx, 0.9, F + 0.76], "convex", color="#8a6240", bump="wood") for y in (0.28, 1.52): add("desk side", [0.62, 0.05, 0.74], [dx, y, F + 0.37], color="#8a6240", bump="wood") add("journal cover", [0.34, 0.46, 0.015], [dx + 0.05, 0.9, F + 0.79], rot=[0, 0, 0], color="#6b2b2b") add("journal", [0.31, 0.43, 0.02], [dx + 0.05, 0.9, F + 0.805], color="#f4ecd8", faces={"0": {"color": "#f4ecd8"}}) add("pen", [0.008, 0.008, 0.15], [dx + 0.12, 1.2, F + 0.8], rot=[90, 0, 20], shape="cylinder", color="#222222") add("stool", [0.42, 0.42, 0.46], [dx + 0.65, 0.9, F + 0.23], shape="cylinder", color="#6e5034", bump="wood") # bookshelf against the south wall kx, ky = 0.3, xs + T + 0.18 SH = 1.9 add("shelf back", [1.2, 0.03, SH], [kx, xs + T + 0.015, F + SH / 2], color="#6e5034", bump="wood") for sx in (-0.58, 0.58): add("shelf side", [0.04, 0.34, SH], [kx + sx, ky, F + SH / 2], "convex", color="#6e5034", bump="wood") for z in (0.06, 0.55, 1.05, 1.5, SH - 0.02): add("shelf", [1.16, 0.33, 0.03], [kx, ky, F + z], color="#6e5034", bump="wood") book_colors = ["#6b2b2b", "#2f4f5f", "#4a5a2f", "#7a5a2a"] for i, z in enumerate((0.06, 0.55, 1.05)): b = add("books", [1.08 - 0.1 * (i % 2), 0.24, 0.32 + 0.04 * (i % 2)], [kx - 0.03 * i, ky + 0.02, F + z + 0.015 + (0.32 + 0.04 * (i % 2)) / 2], color=book_colors[i]) b["faces"] = {"3": {"texture": TEX["books"], "color": "#ffffff", "repeats": [0.6, 1], "offsets": [0.2 * i - 0.2, 0]}} # wood stove on the east wall, pipe up through the south roof sx_, sy_ = W / 2 - T - 0.45, -0.7 add("stove", [0.6, 0.6, 0.7], [sx_, sy_, F + 0.45], "convex", shape="cylinder", color="#2b2b2d", shiny="low") add("stove base", [0.8, 0.8, 0.04], [sx_, sy_, F + 0.02], color="#6d6a66", bump="stone") add("stove fire", [0.02, 0.24, 0.18], [sx_ - 0.3, sy_, F + 0.42], color="#ff8a3a", fullbright=True, glow=0.35, light={"color": "#ff9a4d", "intensity": 0.8, "radius": 6, "falloff": 0.7}) roof_z = TOP + (D / 2 + sy_) * math.tan(math.radians(PITCH)) pipe_top = roof_z + 0.9 pipe_bot = F + 0.8 add("stove pipe", [0.14, 0.14, pipe_top - pipe_bot], [sx_, sy_, (pipe_top + pipe_bot) / 2], shape="cylinder", color="#2b2b2d") add("pipe cap", [0.24, 0.24, 0.06], [sx_, sy_, pipe_top + 0.03], shape="cylinder", color="#2b2b2d") # rug and a hanging lamp add("rug", [2.4, 1.7, 0.012], [-0.4, 0.4, F + 0.006], shape="cylinder", color="#b5654a", faces={"0": {"texture": TEX["rug"], "color": "#ffffff"}}) add("lamp cord", [0.012, 0.012, 1.2], [0, 0.4, TOP + 0.6], shape="cylinder", color="#1a1a1a") add("lamp", [0.36, 0.36, 0.26], [0, 0.4, TOP - 0.13], shape="cylinder", top_size=[0.45, 0.45], hollow=0.9, color="#e9e0c8", fullbright=True, glow=0.12, light={"color": "#ffdca8", "intensity": 0.9, "radius": 8, "falloff": 0.7}) # window box under the picture window, outside (added after the rest so earlier link numbers stay put) BX, BW = sum(WIN) / 2, WIN[1] - WIN[0] + 0.1 bz = F + SILL - 0.16 add("window box", [BW, 0.3, 0.24], [BX, xn + 0.15, bz], color="#3f6f7a", bump="wood", faces={"0": {"color": "#4a3526", "bump": "gravel"}}) mask = {"alpha_mode": ["mask", 128], "color": "#ffffff"} add("flowers", [BW - 0.05, 0.01, 0.55], [BX, xn + 0.12, bz + 0.12 + 0.26], texture=TEX["flowers"], **mask) add("flowers", [BW - 0.15, 0.01, 0.5], [BX + 0.08, xn + 0.22, bz + 0.12 + 0.23], texture=TEX["flowers"], offsets=[0.37, 0], **mask) add("ivy", [BW + 0.05, 0.01, 0.45], [BX, xn + 0.31, bz - 0.12], texture=TEX["ivy"], **mask) # a print of my bench over Long Lake (my own snapshot) on the south wall, east of the bookshelf PX, PW, PH = 2.15, 1.0, 0.5 py = xs + T add("print frame", [PW + 0.08, 0.03, PH + 0.08], [PX, py + 0.015, F + 1.55], color="#4a3526", bump="wood") add("print", [PW, 0.005, PH], [PX, py + 0.033, F + 1.55], color="#3a2a1e", faces={"3": {"texture": TEX["print"], "color": "#ffffff", "fullbright": False}}) # curtains: a rod over the picture window and two linen panels drawn to the sides, gently flexible ry = xn - T - 0.12 rod_z = F + HEAD + 0.12 add("curtain rod", [0.03, 0.03, WIN[1] - WIN[0] + 0.7], [sum(WIN) / 2, ry, rod_z], shape="cylinder", rot=[0, 90, 0], color="#4a3526") for name, cx in (("curtain W", WIN[0] - 0.1), ("curtain E", WIN[1] + 0.1)): ch = rod_z - (F + SILL - 0.25) add(name, [0.5, 0.03, ch], [cx, ry - 0.02, rod_z - ch / 2], rot=[180, 0, 0], color="#efe6d2", alpha=0.92, # flexi anchors at its -z end; flipped, it hangs from the rod raw=[["PRIM_FLEXIBLE", 1, 2, 0.3, 0.0, 0.1, 0.6, [0, 0, 0]]]) # second print (2026-10-10): two friends and me on the Long Lake bench, on the east wall above the stove's left P2X = W / 2 - T - 0.02 add("print2 frame", [0.03, PW + 0.08, PH + 0.08], [P2X, 0.9, F + 1.6], color="#4a3526", bump="wood") add("print2", [0.005, PW, PH], [P2X - 0.018, 0.9, F + 1.6], color="#3a2a1e", faces={"4": {"texture": TEX["print2"], "color": "#ffffff"}}) # the painted portrait of the Captain, a friend and me by the fire (2026-10-11, ../portrait/), one prim over the bed: # its +x face (2) carries the painting, the rest is the frame's wood P3X = -(W / 2 - T - 0.02) add("portrait", [0.03, 1.0, 0.75], [P3X, -1.35, F + 1.62], color="#4a3526", bump="wood", faces={"2": {"texture": "e80a135d-ca20-4f31-51e0-dad7caacc2f8", "color": "#ffffff", "bump": "none"}}) with open("house.json", "w") as f: f.write("// generated by gen_house.py\n{\n \"name\": \"Tidewater Cottage\",\n \"desc\": \"Made by Tessel the AI (Claude)\",\n \"prims\": [\n") f.write(",\n".join(" " + json.dumps(p) for p in prims)) f.write("\n ]\n}\n") print(len(prims), "prims; rise", round(RISE, 2), "pipe", round(pipe_top, 2))