Document licensed Tesla revision and daylight Unreal walkthrough
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
17
decisions/2026-09-15-v008-tesla-and-daylight.md
Normal file
17
decisions/2026-09-15-v008-tesla-and-daylight.md
Normal 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.
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
BIN
renders/v008-daylight-overview.png
Normal file
BIN
renders/v008-daylight-overview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 MiB |
BIN
renders/v008-daylight-tesla.png
Normal file
BIN
renders/v008-daylight-tesla.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 MiB |
BIN
renders/v008-daylight-verandah.png
Normal file
BIN
renders/v008-daylight-verandah.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 MiB |
BIN
renders/v008-tesla-garage.png
Normal file
BIN
renders/v008-tesla-garage.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 MiB |
@@ -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",
|
||||
|
||||
113
site/samford-valley-home/index.html
Normal file
113
site/samford-valley-home/index.html
Normal 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">← 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 →</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/">← 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>
|
||||
8
source/samford-v008-tesla/asset-source.json
Normal file
8
source/samford-v008-tesla/asset-source.json
Normal 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/"
|
||||
}
|
||||
18
source/samford-v008-tesla/blender-final-verification.json
Normal file
18
source/samford-v008-tesla/blender-final-verification.json
Normal 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
|
||||
}
|
||||
40
source/samford-v008-tesla/export_tesla.py
Normal file
40
source/samford-v008-tesla/export_tesla.py
Normal 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)
|
||||
23
source/samford-v008-tesla/finalize_blender.py
Normal file
23
source/samford-v008-tesla/finalize_blender.py
Normal 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)
|
||||
72
source/samford-v008-tesla/replace_tesla.py
Normal file
72
source/samford-v008-tesla/replace_tesla.py
Normal 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)
|
||||
107
source/samford-v008-tesla/unreal-daylight-checks.json
Normal file
107
source/samford-v008-tesla/unreal-daylight-checks.json
Normal 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."
|
||||
}
|
||||
44
source/samford-v008-tesla/unreal-daylight.py
Normal file
44
source/samford-v008-tesla/unreal-daylight.py
Normal 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)
|
||||
24
source/samford-v008-tesla/unreal-fix_sun_direction.py
Normal file
24
source/samford-v008-tesla/unreal-fix_sun_direction.py
Normal 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)
|
||||
24
source/samford-v008-tesla/unreal-remove_opaque_haze.py
Normal file
24
source/samford-v008-tesla/unreal-remove_opaque_haze.py
Normal 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)
|
||||
44
source/samford-v008-tesla/unreal-replace_tesla.py
Normal file
44
source/samford-v008-tesla/unreal-replace_tesla.py
Normal 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)
|
||||
46
source/samford-v008-tesla/unreal-verify_walkthrough.py
Normal file
46
source/samford-v008-tesla/unreal-verify_walkthrough.py
Normal 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)
|
||||
@@ -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."
|
||||
}
|
||||
9
source/samford-v008-tesla/verify_saved_blender.py
Normal file
9
source/samford-v008-tesla/verify_saved_blender.py
Normal 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']))
|
||||
Reference in New Issue
Block a user