Rework Gothic hall as a stone nave interior.
Add gothic ashlar/vault/floor textures, compound piers with transverse ribs, proper lancet arches, textured door-flanking panels, and lightScale for shaft-lit naves. Docs updated in basics and data-and-images. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
1cb9eef935
commit
f9b0fb0496
7 files changed
+501
-61
No files matched your search
@@ -100,41 +100,94 @@ function BaroqueDetails({ width, depth, halfW, halfD, trim }: Props & { trim: st
|
||||
);
|
||||
}
|
||||
|
||||
function MedievalDetails({ halfW, halfD }: Pick<Props, 'halfW' | 'halfD'>) {
|
||||
const torchPositions = useMemo(
|
||||
() =>
|
||||
[
|
||||
[-halfW + 0.2, -halfD * 0.5],
|
||||
[halfW - 0.2, -halfD * 0.5],
|
||||
[-halfW + 0.2, halfD * 0.3],
|
||||
[halfW - 0.2, halfD * 0.3],
|
||||
] as [number, number][],
|
||||
[halfW, halfD]
|
||||
);
|
||||
function GothicDetails({ width, depth, halfW, halfD, trim }: Props & { trim: string }) {
|
||||
// Compound piers along the side walls, spaced by bay, each rising into the
|
||||
// vault springer. Shafts stay flush against the wall (0.16 m proud) so they
|
||||
// never intrude on the ~0.7 m frame hang margin.
|
||||
const bays = useMemo(() => {
|
||||
const spacing = 4.2;
|
||||
const count = Math.max(2, Math.min(9, Math.floor(depth / spacing)));
|
||||
const step = depth / (count + 1);
|
||||
return Array.from({ length: count }, (_, i) => -halfD + step * (i + 1));
|
||||
}, [depth, halfD]);
|
||||
|
||||
const shaftHeight = 3.5;
|
||||
|
||||
return (
|
||||
<group>
|
||||
{torchPositions.map(([x, z], i) => (
|
||||
<group key={i} position={[x, 2.2, z]}>
|
||||
<mesh>
|
||||
<boxGeometry args={[0.08, 0.35, 0.12]} />
|
||||
<meshStandardMaterial color="#3a3028" roughness={0.9} />
|
||||
</mesh>
|
||||
<pointLight position={[0, 0.15, 0.08]} intensity={0.65} distance={5} color="#ff9830" />
|
||||
<mesh position={[0, 0.2, 0.06]}>
|
||||
<sphereGeometry args={[0.06, 8, 8]} />
|
||||
<meshStandardMaterial color="#ffb040" emissive="#ff8010" emissiveIntensity={0.8} toneMapped={false} />
|
||||
</mesh>
|
||||
{bays.map((z, i) => (
|
||||
<group key={i}>
|
||||
{[-1, 1].map((side) => (
|
||||
<group key={side} position={[side * (halfW - 0.09), 0, z]}>
|
||||
{/* Compound pier: a heavier centre shaft flanked by colonnettes */}
|
||||
<mesh position={[0, shaftHeight / 2, 0]}>
|
||||
<cylinderGeometry args={[0.1, 0.115, shaftHeight, 12]} />
|
||||
<meshStandardMaterial color="#a89e88" roughness={0.78} metalness={0.04} />
|
||||
</mesh>
|
||||
{[-0.17, 0.17].map((dz) => (
|
||||
<mesh key={dz} position={[0, shaftHeight / 2, dz]}>
|
||||
<cylinderGeometry args={[0.052, 0.06, shaftHeight, 10]} />
|
||||
<meshStandardMaterial color="#9e9482" roughness={0.82} metalness={0.03} />
|
||||
</mesh>
|
||||
))}
|
||||
{/* Moulded base and foliate capital */}
|
||||
<mesh position={[0, 0.1, 0]}>
|
||||
<boxGeometry args={[0.28, 0.2, 0.52]} />
|
||||
<meshStandardMaterial color="#978d79" roughness={0.85} />
|
||||
</mesh>
|
||||
<mesh position={[0, shaftHeight + 0.12, 0]}>
|
||||
<boxGeometry args={[0.3, 0.24, 0.56]} />
|
||||
<meshStandardMaterial color="#b3a892" roughness={0.7} metalness={0.05} />
|
||||
</mesh>
|
||||
{/* Vault springer resting on the capital */}
|
||||
<mesh position={[0, shaftHeight + 0.36, 0]} rotation={[0, 0, Math.PI / 4]}>
|
||||
<boxGeometry args={[0.17, 0.17, 0.46]} />
|
||||
<meshStandardMaterial color={trim} roughness={0.72} metalness={0.06} />
|
||||
</mesh>
|
||||
</group>
|
||||
))}
|
||||
|
||||
{/* Transverse rib arching across the nave between opposite piers */}
|
||||
<group position={[0, shaftHeight + 0.42, z]}>
|
||||
{Array.from({ length: 9 }, (_, s) => {
|
||||
const segs = 9;
|
||||
const t0 = s / segs;
|
||||
const t1 = (s + 1) / segs;
|
||||
const xAt = (t: number) => -halfW + 0.09 + t * (halfW - 0.09) * 2;
|
||||
const yAt = (t: number) => Math.sin(Math.PI * t) * 0.34;
|
||||
const x0 = xAt(t0);
|
||||
const x1 = xAt(t1);
|
||||
const y0 = yAt(t0);
|
||||
const y1 = yAt(t1);
|
||||
const len = Math.hypot(x1 - x0, y1 - y0);
|
||||
return (
|
||||
<mesh
|
||||
key={s}
|
||||
position={[(x0 + x1) / 2, (y0 + y1) / 2, 0]}
|
||||
rotation={[0, 0, Math.atan2(y1 - y0, x1 - x0)]}
|
||||
>
|
||||
<boxGeometry args={[len * 1.06, 0.13, 0.16]} />
|
||||
<meshStandardMaterial color="#b0a58f" roughness={0.74} metalness={0.05} />
|
||||
</mesh>
|
||||
);
|
||||
})}
|
||||
</group>
|
||||
</group>
|
||||
))}
|
||||
|
||||
{/* Rough stone courses */}
|
||||
{[-halfD + 0.08, halfD - 0.08].map((z, i) => (
|
||||
<mesh key={i} position={[0, 1.5, z]}>
|
||||
<boxGeometry args={[0.04, 3, 0.04]} />
|
||||
<meshStandardMaterial color="#6a6458" roughness={0.98} />
|
||||
{/* Moulded string course running the length of both side walls */}
|
||||
{[-1, 1].map((side) => (
|
||||
<mesh key={side} position={[side * (halfW - 0.05), 2.62, 0]}>
|
||||
<boxGeometry args={[0.12, 0.1, depth - 0.2]} />
|
||||
<meshStandardMaterial color="#b3a892" roughness={0.7} metalness={0.05} />
|
||||
</mesh>
|
||||
))}
|
||||
|
||||
{/* Chancel-style cornice on the end wall */}
|
||||
<mesh position={[0, 3.96, -halfD + 0.1]}>
|
||||
<boxGeometry args={[Math.max(2.4, width - 0.4), 0.16, 0.18]} />
|
||||
<meshStandardMaterial color="#b0a58f" roughness={0.7} metalness={0.05} />
|
||||
</mesh>
|
||||
</group>
|
||||
);
|
||||
}
|
||||
@@ -324,8 +377,8 @@ export default function MovementHallDetails({ style, width, depth, halfW, halfD
|
||||
return <PalazzoDetails style={style} width={width} depth={depth} halfW={halfW} halfD={halfD} trim={trim} />;
|
||||
case 'baroque':
|
||||
return <BaroqueDetails style={style} width={width} depth={depth} halfW={halfW} halfD={halfD} trim={trim} />;
|
||||
case 'medieval':
|
||||
return <MedievalDetails halfW={halfW} halfD={halfD} />;
|
||||
case 'gothic':
|
||||
return <GothicDetails style={style} width={width} depth={depth} halfW={halfW} halfD={halfD} trim={trim} />;
|
||||
case 'byzantine':
|
||||
return <ByzantineDetails halfW={halfW} halfD={halfD} trim={trim} />;
|
||||
case 'neoclassical':
|
||||
|
||||
Reference in new issue
Block a user