Document licensed Tesla revision and daylight Unreal walkthrough

This commit is contained in:
2026-09-15 17:48:37 +10:00
parent ac5407f073
commit cdf0d311ac
24 changed files with 668 additions and 6 deletions

View File

@@ -24,3 +24,6 @@ Read README.md, docs/PROJECT-CONTEXT.md, docs/REQUEST-HISTORY.md and the latest
- Test Unreal collision in a fully initialized play world; editor startup traces can run before physics is ready. Set complex-as-simple collision, refresh the mesh section and save.
- Bedroom bed is to be built into the wall, rigid and quiet, not a free-standing frame. Recorded in decisions/2026-09-11-bed-wall-integrated.md and still to be modelled.
- Latest working revision is v008 in the PRIVATE archive `/home/marcus/projects-private/samford-valley-home-v008`. It contains the licensed 7K Studio Tesla and daylight Unreal scene. Public binaries remain v007. Never publish embedded Tesla geometry; see the v008 decision.
- Do not export Blender volume-only haze as an opaque Unreal mesh. The v007 enclosing haze cube blocked sunlight and was removed in v008. Match Unreal imported material slots by name, not index. Use explicit look-at rotations or keyword Rotator arguments; confirm the sun forward vector points down.

View File

@@ -10,7 +10,11 @@ Read [Project context](docs/PROJECT-CONTEXT.md), [Request history](docs/REQUEST-
Clone using `git clone ssh://git@git.rehbock.xyz:2222/marcus/samford-valley-home.git`. Current files use ordinary Git; no Git LFS client is needed. The existing Git server has LFS disabled.
## Open the current work
## Latest working revision — v008
The 7K Studio Tesla Model 3 and daylight Unreal scene are stored privately at `/home/marcus/projects-private/samford-valley-home-v008` because the car licence restricts redistribution. This public repository retains the distributable v007 binaries and new renders/source/context. See [v008 decision](decisions/2026-09-15-v008-tesla-and-daylight.md).
## Open the public v007 work
- **Blender 5.2.1:** `blender/samford-solarpunk-presentation-tour.blend`. Includes the entire homestead, reading chair and 163 books. Its camera tour has 31 chapters and lasts 2 minutes 35 seconds. Hover over the 3D view and press Space to play; Shift + Left Arrow returns to the start. It opens at the whole-site overview. Earlier bedroom and reading-tour files remain as previous versions.
- **Walkable Unreal Engine 5.8.2:** `unreal/SamfordHomestead/SamfordHomestead.uproject`. Whole-site editor-play prototype, 229 mesh groups and 117 materials. Play, click the viewport, then WASD and mouse; Escape stops. Fresh-launch play testing verified floor collision and movement from the verandah into the house. The earlier meditation-only study is preserved separately.

View File

@@ -0,0 +1,17 @@
# Version 008 — licensed Tesla and daylight walkthrough
15 September 2026. Marcus selected the existing Tesla Model 3 by 7K Studio, then asked for more sunlight to walk around in daylight.
The licensed model replaces the handmade Model Y-inspired placeholder in a private Blender revision and the whole-site Unreal prototype. The original artist geometry, interior, wheels and shaders are retained in Blender, with a simplified fast display. All 31 tour chapters match v007. Unreal uses the reduced artist geometry and adapted PBR materials, with slot assignment by imported material name. A simple car collision box blocks walking; eight floor traces and normal entry movement passed.
Unreal daylight uses a higher neutral sun, brighter sky, reduced native fog and adaptive exposure. Inspection found the old Blender haze volume had imported as an opaque enclosing cube, blocking sunlight and the sky. That non-colliding export was removed; Unreal's native atmosphere/fog now handle the environment. The sun also pointed upward because of positional Rotator argument ordering. An explicit look-at rotation now points the sunlight downward from the northeast, at approximately 52.5 degrees elevation; its forward vector was verified. Actual daylight captures were reviewed.
## Licensed storage
Asset: Tesla Model 3 by 7K Studio. https://www.blendkit.com/asset-gallery-detail/1fc56739-2fd9-447e-b2c1-fee5d9e276b7/
Royalty Free licence: https://www.blendkit.com/docs/licenses/licensing-faq/
The original model is free to acquire but its raw geometry must not be publicly redistributed. The complete v008 Blender file, FBX and Unreal project are stored at `/home/marcus/projects-private/samford-valley-home-v008`, outside the public repository and web root, with restricted directory access. The public repository retains the last distributable v007 binaries, source scripts, this context and permitted rendered images. Do not copy the licensed car or an embedded .blend/.uasset into public Git.
The v007 client film remains unchanged. The pending wall-integrated bed requirement remains unmodelled.

View File

@@ -91,3 +91,7 @@ Marcus requested more overall Blender fidelity, a start on a walkable UE5 simula
## Pending wall-integrated bed requirement
A 11 September 2026 note requests that the bed be rigidly built into wall framing with a considered load path, quiet isolation and Eight Sleep access. This was recorded without a geometry edit in decisions/2026-09-11-bed-wall-integrated.md. The v007 presentation retains the current free-standing bed; incorporate the wall-integrated platform in the next bedroom design revision, with its fixings and load path still subject to engineering.
## Version 008 — Tesla and daylight
Selected the existing 7K Studio Tesla Model 3 and added clear daytime lighting to Unreal. Full licensed revision is stored privately at `/home/marcus/projects-private/samford-valley-home-v008`; public v007 binaries remain available. See `decisions/2026-09-15-v008-tesla-and-daylight.md`. The v007 movie is unchanged.

View File

@@ -59,3 +59,7 @@ Marcus asked for a note on the Blender bedroom: the bed should be built into the
wall rather than stand as free furniture, so it stays rigid and quiet in use.
Recorded as a requirement in `decisions/2026-09-11-bed-wall-integrated.md`. Not
yet modelled — the scene still shows a free-standing bed.
## Version 008 — Tesla and daylight
Selected the existing 7K Studio Tesla Model 3 and added clear daytime lighting to Unreal. Full licensed revision is stored privately at `/home/marcus/projects-private/samford-valley-home-v008`; public v007 binaries remain available. See `decisions/2026-09-15-v008-tesla-and-daylight.md`. The v007 movie is unchanged.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

View File

@@ -1,10 +1,10 @@
{
"milestone": "2026-09-12-v007-presentation-walkthrough",
"milestone": "2026-09-15-v008-tesla-and-daylight",
"files": {
".gitattributes": "d4f9cc15aed223cff7a906452370117fc93992272828cb1efbdd94c61422ad19",
".gitignore": "d38c3a1d58416906185c4c7695ea24f9401be3b610fcce0e624f41dff9fe1675",
"AGENTS.md": "f95132bb06e10888f7948f3277f669cad6353fba87b446a6fb731b6cc423e638",
"README.md": "903a431234608261cb998f6bff42bfc566462253a5f165bf569e3ee12dc71edd",
"AGENTS.md": "79150cb6cc0df63c78bc0ba782f02d49734dba400d71bef56fd867bc7ac6c53b",
"README.md": "142f6a77a2261180015717017fc4e677db9cfa88f14667ba76a0d2da9454d0a9",
"blender/bedroom-sleep-checks.json": "4f28426b4c23e55c956a4c5bc94947706da63e35de455cfaedd8e90e330f1114",
"blender/blender-enhancement-checks.json": "f66943121057ec2e3c2fd0b2bb5d9245721e063b56cfef060598081fce3554e0",
"blender/blender-verification.json": "772764db02a6cec6225d01bf8e38c7680087e53f35614ed48212ea57cbec51dc",
@@ -46,8 +46,9 @@
"decisions/2026-09-10-v006-buddha-garden.md": "aa14fcca78e225563b19ed4a98e335b2f465ed27e12904665c3c654de77b950c",
"decisions/2026-09-11-bed-wall-integrated.md": "31eb04842a0a5904d477d7d28f07792f8b0b1737ac5bb3cbdcc2acb2d7f02a22",
"decisions/2026-09-12-v007-presentation-and-walkthrough.md": "6b3aa18b3660730313f5e0f6a9218c0c868b9734c800456d65c62996cbf7a0b0",
"docs/PROJECT-CONTEXT.md": "c8d69a96c26d3ca1cfe8162982a511542a8b78f6c1c3881fe2f603ab1504c1c1",
"docs/REQUEST-HISTORY.md": "af1168f209ba93270e9adfd93de1d8a548bcee5db6ee795b89bb627c03fb4aae",
"decisions/2026-09-15-v008-tesla-and-daylight.md": "aa5ba8211c49dbe30f5bd205843dec0de6144833907b8739cfa4cea4da0e6a1e",
"docs/PROJECT-CONTEXT.md": "adc652086e3ff36b9958167b0a6649a6020e99c089f836f464c7ab8154d65644",
"docs/REQUEST-HISTORY.md": "0c567e6ce5407e0a3a617d221756457a45645b446a75365d94f66a396d63d465",
"plans/architectural/.gitkeep": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"plans/concept/buddha-garden-plan.svg": "62f622647732bf9556e7d351c06c9dc8576f68e8e0044f91232401972e43e466",
"plans/concept/container-water-plan.svg": "5cf52ea84ae8e222f64881b46807ca869728845c9e1a5b5c80ecfdbfbc3d5fe3",
@@ -78,9 +79,14 @@
"renders/training-area.png": "4534ad28d7ccda82bc93f44f5c0b8b358a3f9e549fe4ba141ca94931812678f8",
"renders/unreal-overview.png": "c01aa10e711c55773b0e087191f6b8857f575f51843e3ebffdf9c7eddd857aca",
"renders/unreal-verandah.png": "d04cd18d2a564e7fd0bc7a9539ffaa590a9e836e6322ba03951eaf0c01e70276",
"renders/v008-daylight-overview.png": "f19f22b21b1227dce3d19b0385b00af757ebc3ca30196dc8f044188f27d39143",
"renders/v008-daylight-tesla.png": "1113d76c2f7edbb98b582f5ee07afad876a40a5810134ec99231233038d46e4c",
"renders/v008-daylight-verandah.png": "8909c2603b0f98c62fc0c4f5d4632172eebdf939819b806f095b557ef870244e",
"renders/v008-tesla-garage.png": "1e706ab3873ba0369d507f89f690e9185b10622cba95a6022b9a989d6b0b0eba",
"site/lidar/processed/.gitkeep": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"site/lidar/raw/.gitkeep": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"site/photos/.gitkeep": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"site/samford-valley-home/index.html": "30d72377b5803e7687dad9ed11000536ac61c477fe48ed0494ed1aefa6dc26bc",
"site/surveys/.gitkeep": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"source/samford-modular/README.md": "e4dd2ed10b0e4f33ddfae86e753cc572d7872bce67ba9aecf66557befc05324d",
"source/samford-modular/build_scene.py": "0bce8490a7f078880c0902b464e9f0202e30f2b44673a7b5378d248850264aa9",
@@ -147,6 +153,19 @@
"source/samford-v007-client-walkthrough/source/refine_film_bedroom.py": "ea6bae1e216a12f0bb7c201fb5bfdc6b39b4eda6045beb2f305c9538d8a18084",
"source/samford-v007-client-walkthrough/source/render_film.py": "77ce49f28c2a47968e00b8c86bae5704d2c683361c2a3689e1cc9da1b8e75f0f",
"source/samford-v007-client-walkthrough/source/verify_blender.py": "7ac14703e84eb6c885d930b9971bd96058de3fe83e4b7c3428cb466bc9231ff6",
"source/samford-v008-tesla/asset-source.json": "1582cdeb9c32b57545020a76def5046257f1ab7c6e4b8cc1ecff72353cadb79c",
"source/samford-v008-tesla/blender-final-verification.json": "2c6c73634c367d29181085dd81ca355accf680da9a3e4de71a4e41675ee28686",
"source/samford-v008-tesla/export_tesla.py": "42f8f7313263cadad2fdb5d2b8f8cf20a3ad969fcb48399f43b99ed09607a049",
"source/samford-v008-tesla/finalize_blender.py": "9d5b1e7bfe0dd9a5576be16be5347545a9bdd7d8185e79c8602dfb9917bffbca",
"source/samford-v008-tesla/replace_tesla.py": "d9764fddd296175c47d60a47849874e3e60c6d541b5ae2a78dcd0e7bb7227cca",
"source/samford-v008-tesla/unreal-daylight-checks.json": "d28e1a42bf4b78d91164e510cab7cba39b5701127a3bf974a281b9f8be3abe32",
"source/samford-v008-tesla/unreal-daylight.py": "f599fa542a520a2991d5a1bd2ccc1e53f7602205207ce58efc010a7fa4890dcb",
"source/samford-v008-tesla/unreal-fix_sun_direction.py": "2c9def0ab36406dab5eaa49604887e88447d67eebd5dcecabe0e4bc3f856afeb",
"source/samford-v008-tesla/unreal-remove_opaque_haze.py": "e9e4edd5c9a0098017e3e86bf3d5e412b329f53d4f7c77f64631b88ca8b091aa",
"source/samford-v008-tesla/unreal-replace_tesla.py": "64563ec67680f065b6ee6f22ea2767a619dc536a2454394daa0ed42894e37cc1",
"source/samford-v008-tesla/unreal-verify_walkthrough.py": "ed426cee0c14a00064ca4d79b0fbc80383f119ada2694ae916949b8bb16d3c0e",
"source/samford-v008-tesla/unreal-walkthrough-verification.json": "4d883f97fd86e2caa9cc5537bde0f74993fbe61cb099ec6f1f9b274413a4f27c",
"source/samford-v008-tesla/verify_saved_blender.py": "ff7b26b54c04b82b773b0b60d192d08717bcf2af393b3d2c4f423c2b07b76384",
"unreal/MeditationRoom.fbx": "7540b71e6cf075e51748db7dc829cf7330c1bfa8cfd8c713041f2127f17ceceb",
"unreal/MeditationRoom.glb": "529770faf5d746f74cc33ccaa84bc1315b1dced2a2e6d14209add716983a9fb6",
"unreal/SamfordHomestead/Config/DefaultEngine.ini": "3448b132adc8ac3f9690fec0a0895d7f3f6d0b1463bf65c81b0d4c822f4c9000",

View File

@@ -0,0 +1,113 @@
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Samford Valley home — Marcus Rehbock</title>
<meta name="description" content="A long-term design project for a simple, extendible homestead in Samford Valley: Blender models, natural materials, food gardens and a walkable Unreal Engine prototype.">
<link rel="canonical" href="https://rehbock.xyz/projects/samford-valley-home/">
<meta property="og:title" content="Samford Valley home — a home that can grow">
<meta property="og:type" content="website"><meta property="og:url" content="https://rehbock.xyz/projects/samford-valley-home/">
<meta property="og:description" content="A family homestead, designed slowly over years. Explore the early Blender and Unreal Engine studies.">
<meta property="og:image" content="https://rehbock.xyz/projects/samford-valley-home/images/v007-presentation-overview.jpg"><meta name="twitter:card" content="summary_large_image">
<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@0,400;0,500;0,600;1,400&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<script type="application/ld+json">{"@context": "https://schema.org", "@type": "CreativeWork", "name": "Samford Valley home", "url": "https://rehbock.xyz/projects/samford-valley-home/", "dateCreated": "2026-09-10", "dateModified": "2026-09-12", "author": {"@id": "https://rehbock.xyz/#person"}, "image": "https://rehbock.xyz/projects/samford-valley-home/images/v007-presentation-overview.jpg"}</script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--text: #1a1a1a;
--text-secondary: #555;
--text-light: #888;
--bg: #faf6ec;
--bg-card: #ffffff;
--border: #e8e5e0;
--serif: 'EB Garamond', Georgia, serif;
--sans: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
}
html { scroll-behavior: smooth; }
body { font-family: var(--sans); background: var(--bg); color: var(--text); line-height: 1.7; -webkit-font-smoothing: antialiased; }
nav { position: fixed; top: 0; left: 0; right: 0; z-index: 100; background: rgba(250, 246, 236, 0.85); backdrop-filter: blur(12px); border-bottom: 1px solid var(--border); }
.nav-inner { max-width: 900px; margin: 0 auto; padding: 16px 32px; display: flex; justify-content: space-between; align-items: center; }
.nav-name { font-family: var(--serif); font-size: 20px; font-weight: 600; color: var(--text); text-decoration: none; }
.nav-back { font-size: 14px; color: var(--text-secondary); text-decoration: none; letter-spacing: 0.3px; }
.nav-back:hover { color: var(--text); }
main { max-width: 760px; margin: 0 auto; padding: 130px 32px 80px; }
h1 { font-family: var(--serif); font-size: 42px; font-weight: 500; letter-spacing: -0.5px; line-height: 1.2; margin-bottom: 12px; }
.lede { font-size: 17px; color: var(--text-secondary); max-width: 560px; margin-bottom: 8px; }
.updated { font-size: 13px; color: var(--text-light); letter-spacing: 0.3px; margin-bottom: 56px; }
h2 { font-family: var(--serif); font-size: 28px; font-weight: 500; letter-spacing: -0.3px; margin: 56px 0 8px; padding-top: 40px; border-top: 1px solid var(--border); }
h2 + p.section-note { font-size: 15px; color: var(--text-light); margin-bottom: 28px; }
.project { display: grid; grid-template-columns: 1fr; gap: 18px; padding: 28px 0; border-top: 1px solid var(--border); }
.project:first-of-type { border-top: 0; }
.shot { display: block; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; background: var(--bg-card); box-shadow: 0 2px 10px rgba(0,0,0,0.05); }
.shot img { display: block; width: 100%; height: auto; }
.project h3 { font-family: var(--serif); font-size: 24px; font-weight: 600; letter-spacing: -0.2px; display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 6px; }
.project h3 a { color: var(--text); text-decoration: none; }
.project h3 a:hover { text-decoration: underline; text-underline-offset: 4px; text-decoration-color: var(--border); }
.status { font-family: var(--sans); font-size: 11px; font-weight: 600; letter-spacing: 1.1px; text-transform: uppercase; padding: 3px 8px; border-radius: 999px; border: 1px solid var(--border); color: var(--text-light); }
.status.live { color: #2f6b3a; border-color: #cfe3d3; background: #eef7f0; }
.status.private { color: #7a5a1e; border-color: #ead9b8; background: #fbf3e2; }
.status.wip { color: #4a5a7a; border-color: #cdd6e6; background: #eef2f9; }
.project p { font-size: 15.5px; color: var(--text-secondary); margin-bottom: 10px; }
.project p a { color: var(--text); text-decoration: underline; text-decoration-color: var(--border); text-underline-offset: 3px; }
.project p a:hover { text-decoration-color: var(--text); }
.why { font-style: italic; }
.why strong { font-style: normal; font-weight: 600; color: var(--text); }
.stack { list-style: none; display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 12px; }
.stack li { font-size: 12px; color: var(--text-secondary); background: var(--bg-card); border: 1px solid var(--border); border-radius: 6px; padding: 2px 8px; letter-spacing: 0.2px; }
.links { font-size: 14px; }
.links a { color: var(--text); text-decoration: none; border-bottom: 1px solid var(--border); padding-bottom: 1px; margin-right: 14px; }
.links a:hover { border-color: var(--text); }
.links .muted { color: var(--text-light); margin-right: 14px; }
.earlier { list-style: none; }
.earlier li { padding: 14px 0; border-top: 1px solid var(--border); font-size: 15.5px; color: var(--text-secondary); }
.earlier li:first-child { border-top: 0; }
.earlier strong { color: var(--text); font-weight: 600; }
.earlier .year { color: var(--text-light); font-size: 13px; margin-left: 8px; }
.colophon { margin-top: 64px; padding-top: 24px; border-top: 1px solid var(--border); font-size: 14px; color: var(--text-light); }
.colophon a { color: var(--text-secondary); }
footer { max-width: 900px; margin: 0 auto; padding: 32px; border-top: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px; font-size: 13px; color: var(--text-light); }
.footer-links { display: flex; gap: 18px; flex-wrap: wrap; }
.footer-links a { color: var(--text-light); text-decoration: none; }
.footer-links a:hover { color: var(--text); }
@media (min-width: 720px) {
.project.has-shot { grid-template-columns: 260px 1fr; align-items: start; }
}
@media (max-width: 768px) {
main { padding: 110px 20px 48px; }
.nav-inner { padding: 14px 20px; }
h1 { font-size: 32px; }
h2 { font-size: 24px; }
}
main{max-width:1080px} .intro{max-width:730px} .lede{max-width:720px} p{margin-bottom:18px} figure{margin:32px 0 48px} figure img{display:block;width:100%;height:auto;border-radius:8px;border:1px solid var(--border)} figcaption{font-size:14px;color:var(--text-secondary);margin-top:10px;max-width:760px} .roadmap{padding-left:22px;margin:22px 0} .roadmap li{margin-bottom:15px} .note{padding:20px 24px;background:#f0eadf;border-left:3px solid #83916b;border-radius:3px} .intro a,main>p a{color:inherit;text-underline-offset:4px} .updated{margin-bottom:28px} blockquote{font-family:var(--serif);font-size:27px;line-height:1.4;margin:30px 0} blockquote cite{display:block;font:13px var(--sans);margin-top:9px;color:var(--text-secondary)}
</style></head><body>
<nav><div class="nav-inner"><a href="/" class="nav-name">Marcus Rehbock</a><a href="/projects/" class="nav-back">&larr; Projects</a></div></nav>
<main><div class="intro"><p class="updated">Started September 2026 · Concept design · A project for the coming years</p>
<h1>A home that can grow.</h1><p class="lede">A simple family homestead in Samford Valley, Queensland. Warm timber, soft clay walls, solar power, food gardens and room to change my mind.</p>
<p>I want to spend the next few years getting this house right. Inspired by Derek Sivers’ article <a href="https://sive.rs/fit">Building without predicting</a>, the starting point is a few straightforward spaces, with future additions left visible as outlines. The house should adapt to life as it unfolds.</p>
<blockquote>“All buildings are predictions. All predictions are wrong.”<cite>— Stewart Brand</cite></blockquote>
<p>The current model brings together a central kitchen, dining and living space, an adjacent parents’ bedroom, a quiet meditation room, an outdoor sauna and shower, and a garage with a workbench and bike storage. Container-enclosed rainwater storage, solar panels, a greenhouse and garden beds are part of the homesteading idea.</p></div>
<figure><a href="images/v007-presentation-overview.jpg"><img src="images/v007-presentation-overview.jpg" alt="Garden-centred revision: aligned pavilions, an oval shared garden, curved covered walkway and flowering beds. Future pavilions remain outlines; the table-tennis deck has been removed." width="1600" height="900" loading="lazy"></a><figcaption>Garden-centred revision: aligned pavilions, an oval shared garden, curved covered walkway and flowering beds. Future pavilions remain outlines; the table-tennis deck has been removed.</figcaption></figure>
<figure><video controls playsinline preload="metadata" poster="images/v007-presentation-overview.jpg" style="display:block;width:100%;height:auto;border-radius:8px"><source src="videos/Samford-Valley-Concept-Film-v007.mp4" type="video/mp4">Your browser can download the film using the link below.</video><figcaption>A 30-second concept film: open living, natural materials, shared meals and room to grow. <a href="videos/Samford-Valley-Concept-Film-v007.mp4">Download the MP4</a>.</figcaption></figure>
<figure><a href="images/v007-presentation-kitchen.jpg"><img src="images/v007-presentation-kitchen.jpg" alt="Detailed timber kitchen with woven pendants, clay walls, copper cookware and marble island" width="1600" height="900" loading="lazy"></a><figcaption>Version 007 adds woven pendants, softer construction edges, natural-finish variation, table settings and fuller garden planting.</figcaption></figure>
<figure><a href="images/v007-unreal-verandah.jpg"><img src="images/v007-unreal-verandah.jpg" alt="Actual Unreal Engine view into the main homestead pavilion" width="1600" height="900" loading="lazy"></a><figcaption>The whole homestead is now an editable first-person Unreal prototype. Walking and floor collision have been tested; the project is in the public repository. The video above is rendered in Blender.</figcaption></figure>
<figure><a href="images/buddha-garden.jpg"><img src="images/buddha-garden.jpg" alt="Seated stone Buddha beside the meditation pavilion and curved garden walk" width="1536" height="864" loading="lazy"></a><figcaption>A quiet garden Buddha beside the meditation room, facing the shared garden court. Weathered stone, a low plinth and a new close-up stop in the Blender tour.</figcaption></figure>
<figure><a href="images/container-water.jpg"><img src="images/container-water.jpg" alt="Dark-green corrugated shipping-container water module with cargo doors and rainwater plumbing" width="1536" height="864" loading="lazy"></a><figcaption>A 20-foot container-style rainwater module replaces the exposed cylinders. Two separate sealed tanks sit inside the steel enclosure; a cutaway end allows inspection in the Blender model.</figcaption></figure>
<figure><a href="images/garden-court.jpg"><img src="images/garden-court.jpg" alt="The central oval garden court, paired flower beds, curved walkway and balanced future pavilion outlines" width="1536" height="864" loading="lazy"></a><figcaption>The garden gives the separate pavilions a shared centre. A north–south axis, paired planting and gently curving connections bring the composition together.</figcaption></figure>
<figure><a href="images/kitchen-copper-marble.jpg"><img src="images/kitchen-copper-marble.jpg" alt="Kitchen refinement: a marble-topped timber island, oven, four-zone induction cooktop, detailed drawers, copper cookware and a recessed sink." width="1536" height="864" loading="lazy"></a><figcaption>Kitchen refinement: a marble-topped timber island, oven, four-zone induction cooktop, detailed drawers, copper cookware and a recessed sink.</figcaption></figure>
<figure><a href="images/garden-flow-dining.jpg"><img src="images/garden-flow-dining.jpg" alt="A ten-place outdoor table with timber benches and end chairs, pergola shade and a nearby tea and matcha preparation counter." width="1536" height="864" loading="lazy"></a><figcaption>A ten-place outdoor table with timber benches and end chairs, pergola shade and a nearby tea and matcha preparation counter.</figcaption></figure>
<figure><a href="images/garden-flow-training.jpg"><img src="images/garden-flow-training.jpg" alt="Covered training beside the garage: a dedicated pull-up and wooden-rings frame, adjustable dumbbells and bench, movable mats and timber access steps." width="1536" height="864" loading="lazy"></a><figcaption>Covered training beside the garage: a dedicated pull-up and wooden-rings frame, adjustable dumbbells and bench, movable mats and timber access steps.</figcaption></figure>
<figure><a href="images/reading-corner.jpg"><img src="images/reading-corner.jpg" alt="Reading-corner study: a timber library filled with books, a linen reading chair and a small side table." width="1600" height="900" loading="lazy"></a><figcaption>Reading-corner study: a timber library filled with books, a linen reading chair and a small side table.</figcaption></figure>
<figure><a href="images/meditation-room.jpg"><img src="images/meditation-room.jpg" alt="The first actual Unreal Engine 5.8.2 render: clay walls, timber, a meditation cushion and candles." width="1600" height="900" loading="lazy"></a><figcaption>The first actual Unreal Engine 5.8.2 render: clay walls, timber, a meditation cushion and candles.</figcaption></figure>
<figure><a href="images/garage.jpg"><img src="images/garage.jpg" alt="The garage study: a Tesla, workshop bench, bicycle storage and rooftop solar." width="1600" height="900" loading="lazy"></a><figcaption>The garage study: a Tesla, workshop bench, bicycle storage and rooftop solar.</figcaption></figure>
<figure><a href="images/bedroom-sleep.jpg"><img src="images/bedroom-sleep.jpg" alt="Bedroom with an Eight Sleep-style cooling cover and bedside hub, oatmeal blackout curtains and a wall-mounted split air conditioner" width="1536" height="864" loading="lazy"></a><figcaption>Bedroom revision: an Eight Sleep-style cover and cooling hub, lined blackout curtains and split-system air conditioning. The outdoor condenser sits behind the bedroom wing.</figcaption></figure>
<div class="intro"><h2>Space for everyday life</h2><p>The plan brings together a covered place to train, an outdoor table for ten, a shared oval garden and gently curving walks ending at a quiet bench. The former table-tennis deck has become a flowering garden. A clear breakfast counter, pantry and freezer storage, and a garden harvest bench make everyday food preparation easier.</p><p>A separate 10 × 10 metre area is reserved for basketball later. It is shown as a dashed outline on the plan; the court surface and hoop have not been built into the concept. The future dwelling spaces also remain outlines.</p><p>The Blender inspection tour has 31 chapters and lasts 2 minutes 35 seconds, with updated views of the garden layout, future pavilions and kitchen.</p></div>
<div class="intro"><h2>Where the project goes next</h2>
<p>The Blender house is the working concept, now accompanied by a short presentation film and a walkable whole-site Unreal prototype. The next step is to refine that prototype for a smooth, packaged client experience.</p>
<ol class="roadmap"><li><strong>Keep refining the house.</strong> Test room proportions, circulation, materials, storage and where future buildings belong.</li><li><strong>Bring in the real site.</strong> Add boundary and contour surveys, site photographs and LiDAR when a property is available.</li><li><strong>Develop coordinated plans.</strong> Bring architectural, structural and services models together with the landscape and access design.</li><li><strong>Develop the Unreal experience.</strong> Refine materials and performance, add interactions and camera tours, then package and test the walkthrough for clients.</li><li><strong>Record the build.</strong> Keep dated decisions, construction photographs and revised models as the house becomes real.</li></ol>
<p><a href="images/concept-site-plan.svg">View the updated concept site plan &rarr;</a></p>
<p class="note">These images are early design studies. The terrain is illustrative; surveyed land, LiDAR and construction drawings have not been added yet.</p>
<h2>Tesla and a daylight walkthrough</h2><p>15 September 2026 — The garage now uses an existing Tesla Model 3 by <a href="https://www.blendkit.com/asset-gallery-detail/1fc56739-2fd9-447e-b2c1-fee5d9e276b7/">7K Studio</a>. The Unreal walkthrough has clear daytime lighting. The licensed scene is stored privately; the public repository retains the earlier distributable model. The film above remains version 007.</p><figure><a href="images/v008-tesla-garage.png"><img src="images/v008-tesla-garage.png" alt="7K Studio Tesla Model 3 in the timber and clay garage, rendered in Blender" width="1600" height="1000" loading="lazy"></a><figcaption>The imported artist model in Blender, with the existing workshop and bikes.</figcaption></figure><figure><a href="images/v008-daylight-overview.png"><img src="images/v008-daylight-overview.png" alt="Actual Unreal Engine daylight view of the homestead" width="1600" height="900" loading="lazy"></a><figcaption>Actual Unreal Engine daylight scene. Walking and Tesla collision have been tested.</figcaption></figure><h2>Project journal</h2><p><strong>12 September 2026 — Presentation and walking prototype.</strong> Refined the Blender scene, created a short client concept film and imported the full site into Unreal Engine with a walking character, collision and lighting. This is an evolving design study; the Unreal project is not yet a packaged client application.</p><p><strong>10 September 2026 — Garden Buddha.</strong> Added a seated stone Buddha beside the meditation pavilion and a 31st tour chapter. The updated Blender model, plan, render and design context are saved in the public project repository.</p><p><strong>10 September 2026 — Container water storage.</strong> Replaced the exposed water tanks with a dark-green container-style enclosure, updated the service path and tour, and added exterior and cutaway renders. The <a href="https://git.rehbock.xyz/marcus/samford-valley-home">project repository is now public</a>, including Blender models, design context and revision history.</p><p><strong>10 September 2026 — A home held together by its garden.</strong> Removed the table-tennis deck, aligned the pavilions and added an oval garden court, curved covered breezeway, smooth paths and thirteen flowering beds. Updated the camera tour and saved the design history, Blender models and supporting files in a private Git repository.</p><p><strong>10 September 2026 — Movement, meals and a detailed kitchen.</strong> Added the training area, ten-place outdoor table and tea counter, table tennis, a future basketball reserve, garden walking loop, quiet bench and convenient food storage. Refined the kitchen with an oven, induction, copper cookware and a marble island. Updated the site plan and saved the 30-chapter Blender tour as milestone v003.</p><p><strong>10 September 2026 — Bedroom comfort.</strong> Added an Eight Sleep-style bed-cooling system, blackout curtains and air conditioning. The updated Blender tour opens in the bedroom; the curtains have a saved closed position for night-time studies.</p><p><strong>10 September 2026 — First saved milestone.</strong> Full Blender homestead and two-minute camera tour; a reading corner with 163 books; a solar-powered garage study; and the first actual Unreal Engine meditation-room render. Working files and a dated snapshot are stored on my server.</p>
<p class="colophon"><a href="/projects/">&larr; Back to all projects</a></p></div></main>
<footer><span>Marcus Rehbock</span><div class="footer-links"><a href="/">Home</a><a href="/projects/">Projects</a><a href="/now/">Now</a></div></footer>
<script async src="https://scripts.simpleanalyticscdn.com/latest.js" data-collect-dnt="true"></script>
</body></html>

View File

@@ -0,0 +1,8 @@
{
"scene_uuid": "b061a256-d972-4ed3-a632-2d4314aa2e99",
"assetBaseId": "1fc56739-2fd9-447e-b2c1-fee5d9e276b7",
"assetId": "e829e99d-fbf3-4d9a-96cf-c62495f35e78",
"author": "7K Studio",
"license": "royalty_free",
"source": "https://www.blendkit.com/asset-gallery-detail/1fc56739-2fd9-447e-b2c1-fee5d9e276b7/"
}

View File

@@ -0,0 +1,18 @@
{
"artist_objects": 45,
"no_old_tesla": true,
"bicycles_and_racks": 86,
"tour_chapters": 31,
"packed_asset_images": true,
"features": {
"ISLAND - honed marble countertop": true,
"FAST | Garden Buddha": true,
"CONTAINER WATER - steel base frame": true,
"Tesla wall connector": true,
"GARAGE WORKSTATION": true
},
"licensed_asset_id": "1fc56739-2fd9-447e-b2c1-fee5d9e276b7",
"status": "PASS",
"tour_matches_v007_exactly": true,
"saved_file_reopened": true
}

View File

@@ -0,0 +1,40 @@
import bpy,json,re
from pathlib import Path
from mathutils import Vector
P=Path(__file__).resolve().parents[1];out=P/'private-assets/transfer';out.mkdir(exist_ok=True)
scene=bpy.context.scene;fast=bpy.data.collections['00 FAST TOUR - lightweight viewport'];fast.hide_viewport=False;bpy.data.collections['DETAIL - full geometry for renders'].hide_viewport=False;bpy.context.view_layer.update()
# Keep existing charging lead endpoint and corresponding plug together.
bpy.data.objects['Tesla plugged charge connector'].location=(-2.67,-21.08,1.56)
# Source file is saved with the static display and all existing tour chapters.
bpy.data.collections['DETAIL - full geometry for renders'].hide_viewport=True
bpy.ops.wm.save_as_mainfile(filepath=str(P/'samford-solarpunk-tesla-v008.blend'))
objects=[bpy.data.objects['FAST | 38 Licensed Tesla Model 3'],bpy.data.objects['FAST | 29 Bicycles and racks']]
# Transfer original mesh, source UVs and material slots. Adapt legacy Blender shaders to UE PBR.
used=list(dict.fromkeys(m for o in objects for m in o.data.materials if m));mats={}
for i,m in enumerate(used):
n=m.name.lower();base=(.055,.055,.055,1);rough=.45;metal=0;opacity=1;coat=0
if 'car paint' in n:base=(.009,.012,.016,1);rough=.16;metal=.35;coat=1
elif 'glass' in n:base=(.035,.07,.07,1);rough=.065;opacity=.28 if 'dark' not in n else .65
elif any(s in n for s in ['steel','metal','mirror','reflection']):base=(.36,.38,.4,1);rough=.23;metal=1
elif 'wood' in n:base=(.36,.19,.08,1);rough=.48
elif 'red' in n:base=(.45,.008,.01,1);rough=.18
elif 'blinker' in n:base=(.8,.22,.012,1);rough=.18
elif any(s in n for s in ['led.front','led.bright','normal lamp']):base=(.85,.85,.82,1);rough=.14
elif 'tire' in n or 'rubber' in n:base=(.015,.018,.018,1);rough=.75
elif 'bright' in n:base=(.58,.59,.6,1);rough=.5
# Preserve original house bicycle colours using their Principled inputs.
if not any(m in bpy.data.objects['FAST | 38 Licensed Tesla Model 3'].data.materials[:] for _ in [0]):
bs=next((x for x in m.node_tree.nodes if x.type=='BSDF_PRINCIPLED'),None) if m.use_nodes else None
if bs:base=tuple(bs.inputs['Base Color'].default_value);rough=bs.inputs['Roughness'].default_value;metal=bs.inputs['Metallic'].default_value
key='M_Tesla_%02d_'%i+re.sub('[^a-zA-Z0-9_]','_',m.name)
mats[key]={'source':m.name,'base_color':base,'roughness':rough,'metallic':metal,'opacity':opacity,'coat':coat}
m.name=key;m.diffuse_color=base
records=[]
for name,o in zip(['Tesla_7K','Bicycles_preserved'],objects):
o.name=name;records.append({'name':name,'materials':[m.name for m in o.data.materials]})
bpy.ops.object.select_all(action='DESELECT')
for o in objects:o.select_set(True)
bpy.context.view_layer.objects.active=objects[0]
bpy.ops.export_scene.fbx(filepath=str(out/'TeslaGarage.fbx'),use_selection=True,object_types={'MESH'},use_mesh_modifiers=True,bake_anim=False,axis_forward='-Y',axis_up='Z',path_mode='AUTO')
(out/'manifest.json').write_text(json.dumps({'materials':mats,'objects':records,'original_asset':'7K Studio Tesla Model 3','note':'Artist geometry and UVs; legacy shaders adapted to UE PBR.'},indent=2))
print('TESLA_EXPORTED',len(mats),flush=True)

View File

@@ -0,0 +1,23 @@
import bpy,json
from pathlib import Path
from mathutils import Vector
P=Path(__file__).resolve().parents[1];s=bpy.context.scene;detail=bpy.data.collections['DETAIL - full geometry for renders'];fast=bpy.data.collections['00 FAST TOUR - lightweight viewport']
cam=bpy.data.objects['VIEW - 7K Tesla garage'];cam.location=(-2.8,-12,2.45);cam.rotation_euler=(Vector((-1.2,-19.2,1.45))-cam.location).to_track_quat('-Z','Y').to_euler();cam.data.lens=36
# Save this close-up as the opening view while retaining the original animated tour camera.
for screen in bpy.data.screens:
for area in screen.areas:
if area.type=='VIEW_3D':
r=area.spaces.active.region_3d;r.view_perspective='PERSP';r.view_location=Vector((-1.5,-19.1,1.4));r.view_distance=8;r.view_rotation=cam.rotation_euler.to_quaternion()
s.frame_set(1);bpy.ops.wm.save_as_mainfile(filepath=str(P/'samford-solarpunk-tesla-v008.blend'))
# Verify unaffected features and artist identity in the final saved file.
names=[o.name for o in bpy.data.objects];car=bpy.data.collections['38 Licensed - Tesla Model 3 by 7K Studio'];old=bpy.data.collections['29 Car and bicycles'];captions=[o.name for o in bpy.data.objects if o.type=='FONT' and ' / ' in o.name]
r={'artist_objects':len(car.objects),'no_old_tesla':not any(o.name.lower().startswith('tesla') for o in old.objects),'bicycles_and_racks':len(old.objects),'tour_chapters':len(captions),'packed_asset_images':all(i.packed_file for i in bpy.data.images if i.source=='FILE' and i.users>0),'features':{k:any(k in n for n in names) for k in ['ISLAND - honed marble countertop','FAST | Garden Buddha','CONTAINER WATER - steel base frame','Tesla wall connector','GARAGE WORKSTATION']},'licensed_asset_id':next(o for o in car.objects if o.parent is None)['asset_id']}
assert r['artist_objects']==45 and r['no_old_tesla'] and r['bicycles_and_racks']==86
assert all(r['features'].values())
r['status']='PASS';(P/'blender-final-verification.json').write_text(json.dumps(r,indent=2))
detail.hide_viewport=False;fast.hide_viewport=True;s.camera=cam
s.render.engine='CYCLES';s.render.resolution_x=1600;s.render.resolution_y=1000;s.render.resolution_percentage=100;s.cycles.samples=40;s.cycles.use_denoising=True
prefs=bpy.context.preferences.addons['cycles'].preferences;prefs.compute_device_type='METAL';prefs.get_devices()
for d in prefs.devices:d.use=d.type=='METAL'
s.cycles.device='GPU';s.render.image_settings.file_format='PNG';s.render.filepath=str(P/'renders/tesla-garage.png');bpy.ops.render.render(write_still=True)
print('FINAL_TESLA_VERIFIED',flush=True)

View File

@@ -0,0 +1,72 @@
import bpy,json,math
from pathlib import Path
from mathutils import Matrix,Vector
P=Path(__file__).resolve().parents[1]
scene=bpy.context.scene;detail=bpy.data.collections['DETAIL - full geometry for renders'];fast=bpy.data.collections['00 FAST TOUR - lightweight viewport'];detail.hide_viewport=False;fast.hide_viewport=True
scene.frame_set(1);bpy.context.view_layer.update()
old=bpy.data.collections['29 Car and bicycles'];removed=[o.name for o in old.objects if o.name.lower().startswith('tesla')]
for n in removed:bpy.data.objects.remove(bpy.data.objects[n],do_unlink=True)
oldproxy=bpy.data.objects.get('FAST | 29 Car and bicycles')
if oldproxy:bpy.data.objects.remove(oldproxy,do_unlink=True)
with bpy.data.libraries.load(str(P/'private-assets/7K-Studio-Tesla-Model-3.blend'),link=False) as (src,dst):dst.objects=src.objects
car=bpy.data.collections.new('38 Licensed - Tesla Model 3 by 7K Studio');detail.children.link(car)
for o in dst.objects:
if o:car.objects.link(o);o.name='7K Tesla | '+o.name
root=next(o for o in car.objects if o.type=='EMPTY' and o.parent is None)
root.location=(-1.7,-19.1,.631);root['creator']='7K Studio';root['license']='BlenderKit Royalty Free - keep out of public source distribution';root['asset_id']='1fc56739-2fd9-447e-b2c1-fee5d9e276b7'
bpy.context.view_layer.update()
# Keep original artist geometry/shaders. Limit only the viewport subdivision cost.
for o in car.objects:
for mod in o.modifiers:
if mod.type=='SUBSURF':mod.levels=min(mod.levels,1);mod.render_levels=min(mod.render_levels,2)
# Static evaluated copy preserves source UVs and materials for fast viewport and export.
def proxy(collection,name,ratio=1):
deps=bpy.context.evaluated_depsgraph_get();copies=[]
for o in collection.objects:
if o.type not in {'MESH','CURVE','FONT'}:continue
ev=o.evaluated_get(deps);me=bpy.data.meshes.new_from_object(ev,depsgraph=deps);ob=bpy.data.objects.new('temporary proxy',me);fast.objects.link(ob);ob.matrix_world=o.matrix_world.copy();copies.append(ob)
# Resolve original material datablocks, never keep evaluated IDs.
mats=[bpy.data.materials.get(m.name) if m else None for m in me.materials];me.materials.clear()
for m in mats:
if m:me.materials.append(m)
bpy.ops.object.select_all(action='DESELECT')
for o in copies:o.select_set(True)
bpy.context.view_layer.objects.active=copies[0];bpy.ops.object.join();ob=copies[0];ob.name=name
bpy.ops.object.transform_apply(location=True,rotation=True,scale=True)
if ratio<1:
d=ob.modifiers.new('Viewport simplification','DECIMATE');d.ratio=ratio;bpy.ops.object.modifier_apply(modifier=d.name)
return ob
fast.hide_viewport=False
bikeproxy=proxy(old,'FAST | 29 Bicycles and racks')
teslaproxy=proxy(car,'FAST | 38 Licensed Tesla Model 3',.35)
fast.hide_viewport=True
# Coil cable on the wall hook instead of leaving a plug floating at the old car.
for o in list(bpy.data.collections['28 Garage and workbench'].objects):
if 'charge' in o.name.lower() or 'cable' in o.name.lower():print('CHARGER',o.name,flush=True)
plug=bpy.data.objects.get('Tesla plugged charge connector')
if plug:plug.location=(-3.66,-20.8,1.77)
# Additional camera does not alter the existing animated 31-stop tour.
camdata=bpy.data.cameras.new('Tesla garage detail');cam=bpy.data.objects.new('VIEW - 7K Tesla garage',camdata);scene.collection.objects.link(cam);cam.location=(-5.1,-12.1,2.55);target=Vector((-1.0,-19.25,1.40));cam.rotation_euler=(target-cam.location).to_track_quat('-Z','Y').to_euler();camdata.lens=39
scene['vehicle_asset']='Tesla Model 3 by 7K Studio; BlenderKit asset 1fc56739-2fd9-447e-b2c1-fee5d9e276b7';scene['revision']='v008 licensed Tesla replacement';scene['public_distribution']='Do not publish this .blend or extracted car; use public source without licensed asset.'
# Record exact source objects for the narrow Unreal replacement.
pts=[o.matrix_world@Vector(v) for o in car.objects if o.type=='MESH' for v in o.bound_box]
r={'removed_placeholder_objects':removed,'artist_objects':len(car.objects),'car_bounds':[[min(v[k] for v in pts),max(v[k] for v in pts)] for k in range(3)],'car_length':max(v.y for v in pts)-min(v.y for v in pts),'fast_car_polygons':len(teslaproxy.data.polygons),'bicycles_preserved':len(old.objects),'source_asset':'1fc56739-2fd9-447e-b2c1-fee5d9e276b7'}
(P/'blender-replacement-checks.json').write_text(json.dumps(r,indent=2))
assert 4.5<r['car_length']<4.9
assert .61<r['car_bounds'][2][0]<.65
assert len(old.objects)>10
bpy.ops.file.pack_all()
# Save user-ready file with fast display and the original tour camera active.
fast.hide_viewport=False;detail.hide_viewport=True
bpy.ops.wm.save_as_mainfile(filepath=str(P/'samford-solarpunk-tesla-v008.blend'))
# Render full geometry in the dedicated garage camera.
detail.hide_viewport=False;fast.hide_viewport=True;scene.camera=cam
scene.render.engine='CYCLES';scene.render.resolution_x=1600;scene.render.resolution_y=1000;scene.render.resolution_percentage=100;scene.cycles.samples=40;scene.cycles.use_denoising=True
prefs=bpy.context.preferences.addons['cycles'].preferences
try:
prefs.compute_device_type='METAL';prefs.get_devices()
for d in prefs.devices:d.use=d.type=='METAL'
scene.cycles.device='GPU'
except Exception:pass
scene.render.image_settings.file_format='PNG';scene.render.filepath=str(P/'renders/tesla-garage.png');bpy.ops.render.render(write_still=True)
print('TESLA_REPLACEMENT_READY',flush=True)

View File

@@ -0,0 +1,107 @@
{
"sun_lux": 65000,
"sun_elevation_degrees": 52.465094,
"sky_intensity": 3.5,
"exposure_EV_range": [
6.5,
16
],
"exposure_bias": 0.5,
"material_slots_resolved_by_imported_name": [
[
"TeslaGarage_Bicycles_preserved",
0,
"M_Tesla_26_Garage_rubber_and_dark_tools"
],
[
"TeslaGarage_Bicycles_preserved",
1,
"M_Tesla_27_Garage_brushed_aluminium"
],
[
"TeslaGarage_Bicycles_preserved",
2,
"M_Tesla_28_Bicycle_ochre_frame"
],
[
"TeslaGarage_Bicycles_preserved",
3,
"M_Tesla_29_Reusable_dark_steel_bolts_and_shoes"
],
[
"TeslaGarage_Bicycles_preserved",
4,
"M_Tesla_30_Bicycle_blue_green_frame"
],
[
"TeslaGarage_Tesla_7K",
0,
"M_Tesla_00_Glass"
],
[
"TeslaGarage_Tesla_7K",
1,
"M_Tesla_01_LightAbsorber"
],
[
"TeslaGarage_Tesla_7K",
2,
"M_Tesla_02_Tire"
],
[
"TeslaGarage_Tesla_7K",
3,
"M_Tesla_03_Plastic_Inventory"
],
[
"TeslaGarage_Tesla_7K",
4,
"M_Tesla_04_Steel"
],
[
"TeslaGarage_Tesla_7K",
5,
"M_Tesla_06_Plastic_Shiny"
],
[
"TeslaGarage_Tesla_7K",
6,
"M_Tesla_08_Car_Paint"
],
[
"TeslaGarage_Tesla_7K",
7,
"M_Tesla_10_Plastic_Inventory_Bright"
],
[
"TeslaGarage_Tesla_7K",
8,
"M_Tesla_21_Carpet"
],
[
"TeslaGarage_Tesla_7K",
9,
"M_Tesla_23_Fabric_Dark"
],
[
"TeslaGarage_Tesla_7K",
10,
"M_Tesla_24_Metal_brake_discs"
]
],
"car_collision": "simple box for walking, detail triangles retained for complex traces",
"level_saved": true,
"removed_opaque_blender_volume": [
"SamfordHomestead_SM_056_11_Camera_and_atmosphere"
],
"sunlight_obstruction_fixed": true,
"sun_forward": [
-0.39649116028239617,
0.4625730204439079,
-0.7929823204683187
],
"sun_rotation": "<Struct 'Rotator' (0x3e3ac12d0) {pitch: -52.465094, yaw: 130.601295, roll: -0.000000}>",
"sun_direction_corrected": true,
"actual_daylight_verified": true,
"visual_verification": "Reviewed fresh Unreal overview, verandah and garage screenshots after correcting the sun direction: directly sunlit terrain and buildings, shaded interiors remain readable."
}

View File

@@ -0,0 +1,44 @@
import unreal as u,time,json,math
from pathlib import Path
P=Path(__file__).resolve().parents[3];A=u.get_editor_subsystem(u.EditorActorSubsystem);E=u.get_editor_subsystem(u.LevelEditorSubsystem);L=u.EditorAssetLibrary;S=u.get_editor_subsystem(u.StaticMeshEditorSubsystem);world=u.get_editor_subsystem(u.UnrealEditorSubsystem).get_editor_world();actors=A.get_all_level_actors();u.EditorPythonScripting.set_keep_python_script_alive(True)
def prop(o,k,v):o.set_editor_property(k,v)
# Resolve the actual imported slot names; FBX can reorder slots.
slots=[]
for path in L.list_assets('/Game/LicensedTesla/Meshes',recursive=True):
mesh=L.load_asset(path)
if not isinstance(mesh,u.StaticMesh):continue
for i,slot in enumerate(mesh.static_materials):
key=str(slot.get_editor_property('imported_material_slot_name'))
material=L.load_asset('/Game/LicensedTesla/Materials/'+key)
assert material,('Missing imported material slot',mesh.get_name(),key)
mesh.set_material(i,material);slots.append([mesh.get_name(),i,key])
if mesh.get_name().endswith('Tesla_7K'):
S.remove_collisions(mesh);S.add_simple_collisions(mesh,u.ScriptCollisionShapeType.BOX);prop(mesh.get_editor_property('body_setup'),'collision_trace_flag',u.CollisionTraceFlag.CTF_USE_SIMPLE_AND_COMPLEX)
L.save_loaded_asset(mesh)
sun=next(a for a in actors if isinstance(a,u.DirectionalLight));sun.set_actor_label('Clear daytime sun');sun.set_actor_rotation(u.MathLibrary.find_look_at_rotation(u.Vector(1200,-1400,2400),u.Vector(0,0,0)),False);sun.light_component.set_intensity(65000);sun.light_component.set_light_color(u.LinearColor(1,.96,.88,1));prop(sun.light_component,'light_source_angle',1.0);prop(sun.light_component,'indirect_lighting_intensity',2.5)
for a in actors:
if isinstance(a,u.SkyLight):
a.light_component.set_intensity(3.5);prop(a.light_component,'real_time_capture',True)
if isinstance(a,u.ExponentialHeightFog):prop(a.component,'fog_density',.001)
if isinstance(a,u.PostProcessVolume):
p=a.settings
for k,v in dict(override_auto_exposure_min_brightness=True,override_auto_exposure_max_brightness=True,auto_exposure_min_brightness=5.5,auto_exposure_max_brightness=11.0,override_auto_exposure_bias=True,auto_exposure_bias=1.2,override_auto_exposure_speed_up=True,auto_exposure_speed_up=3.0,override_auto_exposure_speed_down=True,auto_exposure_speed_down=2.0,override_lumen_scene_lighting_quality=True,lumen_scene_lighting_quality=2.0,override_lumen_final_gather_quality=True,lumen_final_gather_quality=2.0).items():prop(p,k,v)
prop(a,'settings',p)
if isinstance(a,u.RectLight):
a.light_component.set_light_color(u.LinearColor(1,.97,.91,1))
if a.get_actor_label()=='Garage presentation fill':a.light_component.set_intensity(9000)
elif 'verandah bounce' in a.get_actor_label():a.light_component.set_intensity(6000)
E.save_current_level();L.save_directory('/Game/LicensedTesla',only_if_is_dirty=True,recursive=True)
r={'sun_lux':65000,'sun_elevation_degrees':52,'sky_intensity':3.5,'exposure_EV_range':[5.5,11.0],'exposure_bias':1.2,'material_slots_resolved_by_imported_name':slots,'car_collision':'simple box for walking, detail triangles retained for complex traces','level_saved':True}
(P/'unreal-daylight-checks.json').write_text(json.dumps(r,indent=2))
for c in ['r.HighResScreenshotDelay 64','r.AntiAliasingMethod 2','r.TemporalAASamples 64']:u.SystemLibrary.execute_console_command(world,c)
cams=[next(a for a in actors if a.get_actor_label()==n) for n in ['CAM - Verandah','CAM - Overview','CAM - Licensed Tesla garage']];state={'start':time.monotonic(),'i':0,'task':None}
def tick(dt):
if time.monotonic()-state['start']<30:return
if state['task'] is None:
u.AutomationLibrary.finish_loading_before_screenshot();cam=cams[state['i']];u.EditorLevelLibrary.set_level_viewport_camera_info(cam.get_actor_location(),cam.get_actor_rotation());state['task']=u.AutomationLibrary.take_high_res_screenshot(1600,1000,str(P/'renders'/('daylight-'+['verandah','overview','tesla'][state['i']]+'.png')),camera=cam,delay=5)
elif state['task'].is_task_done():
state['i']+=1;state['task']=None
if state['i']==3:
u.unregister_slate_post_tick_callback(handle);u.log('DAYLIGHT_CAPTURED');u.SystemLibrary.quit_editor()
handle=u.register_slate_post_tick_callback(tick)

View File

@@ -0,0 +1,24 @@
import unreal as u,time,json
from pathlib import Path
P=Path(__file__).resolve().parents[3];A=u.get_editor_subsystem(u.EditorActorSubsystem);E=u.get_editor_subsystem(u.LevelEditorSubsystem);world=u.get_editor_subsystem(u.UnrealEditorSubsystem).get_editor_world();u.EditorPythonScripting.set_keep_python_script_alive(True)
actors=A.get_all_level_actors()
sun=next(a for a in actors if isinstance(a,u.DirectionalLight))
sun.set_actor_rotation(u.MathLibrary.find_look_at_rotation(u.Vector(1200,-1400,2400),u.Vector(0,0,0)),False)
sun.set_actor_scale3d(u.Vector(1,1,1))
direction=sun.get_actor_forward_vector()
assert direction.z < -.5,str(direction)
sun.light_component.set_intensity(65000)
E.save_current_level()
f=P/'unreal-daylight-checks.json';r=json.loads(f.read_text());r['sun_forward']=[direction.x,direction.y,direction.z];r['sun_rotation']=str(sun.get_actor_rotation());r['sun_direction_corrected']=True;r['sun_elevation_degrees']=52.46;f.write_text(json.dumps(r,indent=2))
for c in ['r.HighResScreenshotDelay 64','r.AntiAliasingMethod 2','r.TemporalAASamples 64']:u.SystemLibrary.execute_console_command(world,c)
actors=A.get_all_level_actors()
cams=[next(a for a in actors if a.get_actor_label()==n) for n in ['CAM - Overview','CAM - Verandah','CAM - Licensed Tesla garage']];state={'start':time.monotonic(),'i':0,'task':None}
def tick(dt):
if time.monotonic()-state['start']<25:return
if state['task'] is None:
u.AutomationLibrary.finish_loading_before_screenshot();cam=cams[state['i']];u.EditorLevelLibrary.set_level_viewport_camera_info(cam.get_actor_location(),cam.get_actor_rotation());state['task']=u.AutomationLibrary.take_high_res_screenshot(1600,1000,str(P/'renders'/('daylight-'+['overview','verandah','tesla'][state['i']]+'.png')),camera=cam,delay=6)
elif state['task'].is_task_done():
state['i']+=1;state['task']=None
if state['i']==3:
u.unregister_slate_post_tick_callback(handle);u.log('CORRECTED_SUN_CAPTURED');u.SystemLibrary.quit_editor()
handle=u.register_slate_post_tick_callback(tick)

View File

@@ -0,0 +1,24 @@
import unreal as u,time,json
from pathlib import Path
P=Path(__file__).resolve().parents[3];A=u.get_editor_subsystem(u.EditorActorSubsystem);E=u.get_editor_subsystem(u.LevelEditorSubsystem);world=u.get_editor_subsystem(u.UnrealEditorSubsystem).get_editor_world();u.EditorPythonScripting.set_keep_python_script_alive(True)
actors=A.get_all_level_actors();removed=[]
for a in actors:
if 'SM_056_11_Camera_and_atmosphere' in a.get_actor_label():removed.append(a.get_actor_label());A.destroy_actor(a)
assert len(removed)<=1,removed
for a in A.get_all_level_actors():
if isinstance(a,u.PostProcessVolume):
p=a.settings;p.auto_exposure_min_brightness=6.5;p.auto_exposure_max_brightness=16;p.auto_exposure_bias=.5;a.set_editor_property('settings',p)
E.save_current_level()
f=P/'unreal-daylight-checks.json';r=json.loads(f.read_text());r['removed_opaque_blender_volume']=removed or r.get('removed_opaque_blender_volume',[]);r['exposure_EV_range']=[6.5,16];r['exposure_bias']=.5;r['sunlight_obstruction_fixed']=True;f.write_text(json.dumps(r,indent=2))
for c in ['r.HighResScreenshotDelay 64','r.AntiAliasingMethod 2','r.TemporalAASamples 64']:u.SystemLibrary.execute_console_command(world,c)
actors=A.get_all_level_actors()
cams=[next(a for a in actors if a.get_actor_label()==n) for n in ['CAM - Overview','CAM - Verandah','CAM - Licensed Tesla garage']];state={'start':time.monotonic(),'i':0,'task':None}
def tick(dt):
if time.monotonic()-state['start']<25:return
if state['task'] is None:
u.AutomationLibrary.finish_loading_before_screenshot();cam=cams[state['i']];u.EditorLevelLibrary.set_level_viewport_camera_info(cam.get_actor_location(),cam.get_actor_rotation());state['task']=u.AutomationLibrary.take_high_res_screenshot(1600,1000,str(P/'renders'/('daylight-'+['overview','verandah','tesla'][state['i']]+'.png')),camera=cam,delay=6)
elif state['task'].is_task_done():
state['i']+=1;state['task']=None
if state['i']==3:
u.unregister_slate_post_tick_callback(handle);u.log('TRUE_DAYLIGHT_CAPTURED');u.SystemLibrary.quit_editor()
handle=u.register_slate_post_tick_callback(tick)

View File

@@ -0,0 +1,44 @@
import unreal as u,json,math,time,traceback
from pathlib import Path
P=Path(__file__).resolve().parents[3];D=json.loads((P/'private-assets/transfer/manifest.json').read_text());L=u.EditorAssetLibrary;M=u.MaterialEditingLibrary;A=u.get_editor_subsystem(u.EditorActorSubsystem);E=u.get_editor_subsystem(u.LevelEditorSubsystem);T=u.AssetToolsHelpers.get_asset_tools();u.EditorPythonScripting.set_keep_python_script_alive(True)
def prop(o,k,v):o.set_editor_property(k,v)
def scalar(m,v,p):
n=M.create_material_expression(m,u.MaterialExpressionConstant);prop(n,'r',v);M.connect_material_property(n,'',p)
materials={}
for key,r in D['materials'].items():
m=L.load_asset('/Game/LicensedTesla/Materials/'+key) or T.create_asset(key,'/Game/LicensedTesla/Materials',u.Material,u.MaterialFactoryNew());M.delete_all_material_expressions(m);prop(m,'two_sided',True)
n=M.create_material_expression(m,u.MaterialExpressionConstant3Vector);prop(n,'constant',u.LinearColor(*r['base_color']));M.connect_material_property(n,'',u.MaterialProperty.MP_BASE_COLOR)
scalar(m,r['roughness'],u.MaterialProperty.MP_ROUGHNESS);scalar(m,r['metallic'],u.MaterialProperty.MP_METALLIC)
if r['opacity']<1:
prop(m,'blend_mode',u.BlendMode.BLEND_TRANSLUCENT);scalar(m,r['opacity'],u.MaterialProperty.MP_OPACITY)
M.recompile_material(m);L.save_loaded_asset(m);materials[key]=m
opts=u.FbxImportUI()
for k,v in dict(import_mesh=True,import_materials=False,import_textures=False,import_as_skeletal=False,import_animations=False,mesh_type_to_import=u.FBXImportType.FBXIT_STATIC_MESH).items():prop(opts,k,v)
for k,v in dict(combine_meshes=False,auto_generate_collision=False,generate_lightmap_u_vs=False,convert_scene=True,force_front_x_axis=False).items():prop(opts.static_mesh_import_data,k,v)
t=u.AssetImportTask()
for k,v in dict(filename=str(P/'private-assets/transfer/TeslaGarage.fbx'),destination_path='/Game/LicensedTesla/Meshes',automated=True,replace_existing=True,save=True,options=opts).items():prop(t,k,v)
T.import_asset_tasks([t]);meshes=[L.load_asset(p) for p in t.imported_object_paths];meshes=[m for m in meshes if isinstance(m,u.StaticMesh)];assert len(meshes)==2
before=A.get_all_level_actors();old=[a for a in before if '29_Car_and_bicycles' in a.get_actor_label()];assert len(old)>0,'Original car groups not found'
for a in old:A.destroy_actor(a)
for mesh in meshes:
rec=next(r for r in D['objects'] if mesh.get_name().endswith(r['name']))
for i,key in enumerate(rec['materials']):mesh.set_material(i,materials[key])
body=mesh.get_editor_property('body_setup');prop(body,'collision_trace_flag',u.CollisionTraceFlag.CTF_USE_COMPLEX_AS_SIMPLE);prop(body,'double_sided_geometry',True)
for i in range(len(rec['materials'])):u.get_editor_subsystem(u.StaticMeshEditorSubsystem).enable_section_collision(mesh,True,0,i)
a=A.spawn_actor_from_class(u.StaticMeshActor,u.Vector());a.static_mesh_component.set_static_mesh(mesh);a.static_mesh_component.set_collision_profile_name('BlockAll');a.set_actor_label('LICENSED - '+rec['name']);a.set_folder_path('Licensed Tesla - exclude from public source');L.save_loaded_asset(mesh)
car=next(m for m in meshes if m.get_name().endswith('Tesla_7K'));bounds=car.get_bounds();assert 200<bounds.box_extent.y<260,str(bounds)
# Camera from the garage entrance, retaining the original walking spawn and all existing cameras.
cp=u.Vector(-280,1200,245);target=u.Vector(-120,1920,145);cam=A.spawn_actor_from_class(u.CameraActor,cp,u.MathLibrary.find_look_at_rotation(cp,target));cam.set_actor_label('CAM - Licensed Tesla garage');cam.camera_component.set_field_of_view(50);prop(cam.camera_component,'aspect_ratio',1.6)
# Gentle local fill makes dark automobile interiors readable in the prototype.
light=A.spawn_actor_from_class(u.RectLight,u.Vector(-150,1550,300),u.Rotator(-20,90,0));light.set_actor_label('Garage presentation fill');light.light_component.set_mobility(u.ComponentMobility.MOVABLE);light.light_component.set_intensity(800);prop(light.light_component,'attenuation_radius',700);prop(light.light_component,'source_width',300);prop(light.light_component,'source_height',180)
E.save_current_level();L.save_directory('/Game/LicensedTesla',only_if_is_dirty=True,recursive=True)
report={'removed_placeholder_groups':len(old),'new_meshes':len(meshes),'materials':len(materials),'car_bounds_cm':str(bounds),'level_saved':True,'source':'7K Studio Tesla Model 3','public_distribution':False}
(P/'unreal-tesla-checks.json').write_text(json.dumps(report,indent=2))
state={'start':time.monotonic(),'task':None}
def tick(dt):
if time.monotonic()-state['start']<25:return
if state['task'] is None:
u.AutomationLibrary.finish_loading_before_screenshot();state['task']=u.AutomationLibrary.take_high_res_screenshot(1600,1000,str(P/'renders/unreal-tesla-garage.png'),camera=cam,delay=3)
elif state['task'].is_task_done():
u.unregister_slate_post_tick_callback(handle);u.log('TESLA_UNREAL_READY');u.SystemLibrary.quit_editor()
handle=u.register_slate_post_tick_callback(tick)

View File

@@ -0,0 +1,46 @@
import unreal as u,json,time,math,traceback
from pathlib import Path
ROOT=Path(__file__).resolve().parents[3];LEVEL=u.get_editor_subsystem(u.LevelEditorSubsystem);EDITOR=u.get_editor_subsystem(u.UnrealEditorSubsystem);report={'floor_traces':{},'movement':None};u.EditorPythonScripting.set_keep_python_script_alive(True)
state={'start':time.monotonic(),'phase':'load','t':0,'positions':[]}
def pos(v):return u.Vector(v[0]*100,-v[1]*100,v[2]*100)
def tick(dt):
try:
elapsed=time.monotonic()-state['start']
if state['phase']=='finish':
if time.monotonic()-state['t']>3:
u.unregister_slate_post_tick_callback(handle);u.log('HOMESTEAD_WALK_VERIFIED '+json.dumps(report['movement']));u.SystemLibrary.quit_editor()
return
if elapsed>90:raise RuntimeError('Play-in-editor movement test timed out')
if state['phase']=='load':
if elapsed<12:return
u.AutomationLibrary.finish_loading_before_screenshot();LEVEL.editor_request_begin_play();state['phase']='settle';state['t']=time.monotonic();return
game=EDITOR.get_game_world()
if not game:return
pawn=u.GameplayStatics.get_player_pawn(game,0)
if not pawn:return
if state['phase']=='settle':
if time.monotonic()-state['t']<4:return
assert 'HomesteadWalker' in pawn.get_class().get_name(),pawn.get_class().get_name()
for name,xy in [('verandah',(0,4)),('living',(-1.8,1)),('corridor',(-7.5,-1.8)),('bedroom',(-10.7,-3.5)),('meditation',(-11.8,10.8)),('garage',(2,-18)),('garden',(0,13)),('training',(-10,-19))]:
result=u.SystemLibrary.line_trace_single(game,pos((*xy,2.9)),pos((*xy,-2)),u.TraceTypeQuery.TRACE_TYPE_QUERY1,True,[pawn],u.DrawDebugTrace.NONE,True);assert result is not None,name;report['floor_traces'][name]='hit'
p=pawn.get_actor_location();state['initial']=[p.x,p.y,p.z];assert 170<p.z<240,('Spawn not on floor',p.z);state['phase']='car_settle';state['t']=time.monotonic();pawn.set_actor_location(u.Vector(-170,1500,153),False,True)
elif state['phase']=='car_settle':
if time.monotonic()-state['t']<1:return
state['phase']='car_walk';state['t']=time.monotonic()
elif state['phase']=='car_walk':
pawn.add_movement_input(u.Vector(0,1,0),1)
if time.monotonic()-state['t']>2.5:
q=pawn.get_actor_location();assert 1570<q.y<1680,('Car did not stop walking capsule',q)
report['tesla_collision']={'walk_stopped_before_car':True,'position_cm':[q.x,q.y,q.z]}
pawn.set_actor_location(u.Vector(*state['initial']),False,True);state['phase']='walk_reset';state['t']=time.monotonic()
elif state['phase']=='walk_reset':
if time.monotonic()-state['t']<1:return
state['phase']='walk';state['t']=time.monotonic()
elif state['phase']=='walk':
p=pawn.get_actor_location();state['positions'].append([p.x,p.y,p.z]);pawn.add_movement_input(u.Vector(0,1,0),1)
if time.monotonic()-state['t']>2.5:
a=state['initial'];dist=math.hypot(p.x-a[0],p.y-a[1]);assert dist>100,('No meaningful movement',dist);assert 170<p.z<240,('Pawn left walking floor',p.z)
report['movement']={'pawn':pawn.get_class().get_name(),'start_cm':a,'end_cm':[p.x,p.y,p.z],'distance_cm':dist,'movement_mode':str(pawn.character_movement.movement_mode),'controller_possessed':pawn.get_controller() is not None,'sampled_positions':len(state['positions'])};report['status']='PASS: daylight level, Tesla blocks walking, eight floor traces and possessed character walking from verandah into living entry';(ROOT/'unreal-walkthrough-verification.json').write_text(json.dumps(report,indent=2));LEVEL.editor_request_end_play();state['phase']='finish';state['t']=time.monotonic()
except Exception:
report['status']='FAILED';report['error']=traceback.format_exc();(ROOT/'unreal-walkthrough-verification.json').write_text(json.dumps(report,indent=2));u.log_error(report['error']);u.unregister_slate_post_tick_callback(handle);LEVEL.editor_request_end_play();u.SystemLibrary.quit_editor()
handle=u.register_slate_post_tick_callback(tick)

View File

@@ -0,0 +1,39 @@
{
"floor_traces": {
"verandah": "hit",
"living": "hit",
"corridor": "hit",
"bedroom": "hit",
"meditation": "hit",
"garage": "hit",
"garden": "hit",
"training": "hit"
},
"movement": {
"pawn": "BP_HomesteadWalker_C",
"start_cm": [
0.0,
-455.0,
208.91514610554694
],
"end_cm": [
0.0,
-109.60077457824171,
204.1499967251696
],
"distance_cm": 345.3992254217583,
"movement_mode": "<MovementMode.MOVE_WALKING: 1>",
"controller_possessed": true,
"sampled_positions": 59
},
"tesla_collision": {
"walk_stopped_before_car": true,
"position_cm": [
-170.0,
1651.1851263218496,
154.14999469910472
]
},
"status": "PASS: Tesla blocks walking, eight floor traces and possessed character walking from verandah into living entry",
"verification_scope": "Play-in-editor checks preceded final lighting-only corrections and removal of the non-colliding opaque haze box; fresh final daylight screenshots are recorded separately."
}

View File

@@ -0,0 +1,9 @@
import bpy,json
from pathlib import Path
P=Path(__file__).resolve().parents[1]
def snap():
c=bpy.data.collections['22 PLAY - guided camera tour'];s=bpy.context.scene
return {'captions':{o.name:o.data.body for o in c.objects if o.type=='FONT'},'frame_range':[s.frame_start,s.frame_end],'camera':s.camera.name,'markers':[(m.name,m.frame) for m in s.timeline_markers]}
bpy.ops.wm.open_mainfile(filepath=str(P/'base/samford-solarpunk-presentation-tour.blend'),use_scripts=False);a=snap()
bpy.ops.wm.open_mainfile(filepath=str(P/'samford-solarpunk-tesla-v008.blend'),use_scripts=False);b=snap();assert a==b,('Tour changed',a,b)
p=P/'blender-final-verification.json';r=json.loads(p.read_text());r['tour_chapters']=len(b['captions']);r['tour_matches_v007_exactly']=True;r['saved_file_reopened']=True;p.write_text(json.dumps(r,indent=2));print('SAVED_BLEND_VERIFIED',len(b['captions']))