diff --git a/components/configurator/scene.tsx b/components/configurator/scene.tsx
index add7578..fc16a0d 100644
--- a/components/configurator/scene.tsx
+++ b/components/configurator/scene.tsx
@@ -1,182 +1,274 @@
"use client";
import { Canvas } from "@react-three/fiber";
-import { OrbitControls, PerspectiveCamera, Environment, ContactShadows } from "@react-three/drei";
+import {
+ OrbitControls,
+ PerspectiveCamera,
+ Environment,
+ ContactShadows,
+} from "@react-three/drei";
import { Door3DEnhanced } from "./door-3d-enhanced";
import { useConfiguratorStore } from "@/lib/store";
+import {
+ STELRUIMTE,
+ WALL_THICKNESS,
+ TAATS_PIVOT_OFFSET,
+ mmToMeters,
+} from "@/lib/door-models";
import * as THREE from "three";
-function LivingRoom({ doorWidth, doorHeight }: { doorWidth: number; doorHeight: number }) {
- const wallThickness = 0.15;
- const roomWidth = 8;
- const roomDepth = 6;
- const roomHeight = 3;
+// ============================================
+// WALL MATERIALS
+// ============================================
- // Calculate dynamic doorway dimensions
- const doorwayWidth = doorWidth + wallThickness * 2 + 0.1; // Extra margin
- const doorwayHeight = doorHeight + wallThickness + 0.1;
+/** Smooth painted wall surface */
+const WallMaterial = () => (
+
+);
+
+/** Stucco/plaster reveal surface (inside the door opening) */
+const RevealMaterial = () => (
+
+);
+
+/** Floor material - light wood */
+const FloorMaterial = () => (
+
+);
+
+// ============================================
+// WALL CONTAINER WITH PRECISE HOLE
+// ============================================
+
+/**
+ * Creates a wall with a precise rectangular opening (sparing).
+ * Uses 4 boxes to form the wall around the hole instead of CSG.
+ * The reveal (inner edge of the hole) has a plaster texture.
+ */
+function WallContainer({
+ holeWidth,
+ holeHeight,
+ wallThickness,
+}: {
+ holeWidth: number; // meters - sparingsmaat width
+ holeHeight: number; // meters - sparingsmaat height
+ wallThickness: number; // meters
+}) {
+ const wallWidth = 4.0; // Total wall width in meters
+ const wallHeight = 3.0; // Total wall height (floor to ceiling)
+
+ // Half dimensions for positioning
+ const halfHoleW = holeWidth / 2;
+ const halfWallT = wallThickness / 2;
+
+ // Left wall section: from left edge to hole left edge
+ const leftSectionWidth = (wallWidth - holeWidth) / 2;
+ const leftSectionX = -(halfHoleW + leftSectionWidth / 2);
+
+ // Right wall section: from hole right edge to right edge
+ const rightSectionWidth = leftSectionWidth;
+ const rightSectionX = halfHoleW + rightSectionWidth / 2;
+
+ // Top section: above hole, full width
+ const topSectionHeight = wallHeight - holeHeight;
+ const topSectionY = holeHeight + topSectionHeight / 2;
+
+ // Stelruimte gap (visual indicator)
+ const gapPerSide = mmToMeters(STELRUIMTE / 2);
return (
-
- {/* Floor - Modern light wood */}
-
-
-
+
+ {/* === MAIN WALL SECTIONS === */}
+
+ {/* Left wall section */}
+
+
+
- {/* Back Wall with Dynamic Doorway */}
-
- {/* Left Pillar - Dynamic height */}
-
-
-
-
-
- {/* Right Pillar - Dynamic height */}
-
-
-
-
-
- {/* Doorway Frame - Left */}
-
-
-
-
-
- {/* Doorway Frame - Right */}
-
-
-
-
-
- {/* Doorway Frame - Top (Lintel) */}
-
-
-
-
-
- {/* Main Wall - Left Section */}
-
-
-
-
-
- {/* Main Wall - Right Section */}
-
-
-
-
-
- {/* Main Wall - Top Section (above doorway) */}
-
-
-
-
-
-
- {/* Left Wall */}
-
-
-
+ {/* Right wall section */}
+
+
+
- {/* Right Wall */}
-
-
-
+ {/* Top section (above hole, full wall width) */}
+ {topSectionHeight > 0.01 && (
+
+
+
+
+ )}
+
+ {/* === REVEAL SURFACES (inside the hole) === */}
+ {/* These are the plaster/stucco edges visible inside the opening */}
+
+ {/* Left reveal */}
+
+
+
- {/* Ceiling */}
-
-
-
+ {/* Right reveal */}
+
+
+
- {/* Decorative Elements - Baseboard Left */}
-
-
-
+ {/* Top reveal */}
+
+
+
- {/* Decorative Elements - Baseboard Right */}
-
-
-
+ {/* === REVEAL DEPTH SURFACES (visible sides inside the opening) === */}
+ {/* Left inner wall (visible when looking at the opening from the side) */}
+
+
+
+
+
+ {/* Right inner wall */}
+
+
+
+
+
+ {/* Top inner wall (lintel reveal) */}
+
+
+
+
+
+ {/* === FLOOR === */}
+
+
+
+
+
+ {/* Floor behind wall */}
+
+
+
+
+
+ {/* === BASEBOARD (Plint) === */}
+ {/* Left side baseboard */}
+
+
+
+
+
+ {/* Right side baseboard */}
+
+
+
);
}
-function DoorWithRoom() {
- const { doorLeafWidth, height } = useConfiguratorStore();
+// ============================================
+// DOOR + WALL COMPOSITION
+// ============================================
- // Convert mm to meters for 3D scene
- const doorWidth = doorLeafWidth / 1000;
- const doorHeight = height / 1000;
+function DoorInWall() {
+ const { doorType, doorLeafWidth, height, holeWidth } = useConfiguratorStore();
+
+ // Convert mm to meters
+ const doorWidthM = mmToMeters(doorLeafWidth);
+ const doorHeightM = mmToMeters(height);
+ const wallThicknessM = mmToMeters(WALL_THICKNESS);
+
+ // Sparingsmaat = the hole in the wall
+ // Use doorLeafWidth + stelruimte as the opening size
+ const stelruimteM = mmToMeters(STELRUIMTE);
+ const holeWidthM = doorWidthM + stelruimteM;
+ const holeHeightM = doorHeightM + stelruimteM / 2; // 5mm top tolerance
+
+ // Door Z position depends on type
+ // Taats: centered in wall thickness (pivot at center)
+ // Scharnier/Paneel: flush with front wall face
+ const doorZOffset = doorType === 'taats' ? 0 : wallThicknessM * 0.15;
return (
<>
-
-
+ {/* The wall with precise opening */}
+
+
+ {/* The door, positioned inside the wall opening */}
+
+
+
>
);
}
+// ============================================
+// LIGHTING
+// ============================================
+
function Lighting() {
return (
<>
{/* Ambient for overall illumination */}
-
+
- {/* Main directional light (sunlight from window) */}
+ {/* Main directional light (sunlight angle) */}
- {/* Fill light from opposite side */}
-
+ {/* Fill light from behind/left to illuminate reveal */}
+
- {/* Subtle top light */}
-
+ {/* Subtle light from viewer side to show depth in reveal */}
+
+
+ {/* Top down light for reveal shadows */}
+
>
);
}
+// ============================================
+// MAIN SCENE EXPORT
+// ============================================
+
export function Scene3D() {
return (
);
}
diff --git a/lib/door-models.ts b/lib/door-models.ts
index 87baf23..3e8c2b2 100644
--- a/lib/door-models.ts
+++ b/lib/door-models.ts
@@ -39,6 +39,39 @@ export const RAIL_HEIGHT_ROBUST = 40; // mm - Standard robust rails (same as pro
*/
export const TAATS_PIVOT_OFFSET = 60; // mm - Pivot axis offset from wall for Taats doors
+/**
+ * Wall Mounting Dimensions (Sparingsmaat / Deurmaat)
+ * Dutch building standard: Sparingsmaat = rough wall opening
+ */
+export const STELRUIMTE = 10; // mm - Total tolerance between wall and frame (5mm per side)
+export const HANGNAAD = 3; // mm - Gap between frame and door leaf per side
+export const WALL_THICKNESS = 150; // mm - Standard interior wall thickness
+
+/**
+ * Calculate mounting dimensions from Sparingsmaat (wall opening).
+ *
+ * Sparingsmaat (input) -> Frame -> Door Leaf
+ * Frame = Sparingsmaat - STELRUIMTE (10mm tolerance)
+ * DoorLeaf = Frame - 2*PROFILE_WIDTH - 2*HANGNAAD (6mm gap)
+ */
+export function calculateMountingDimensions(sparingsmaatWidth: number, sparingsmaatHeight: number) {
+ const frameOuterWidth = sparingsmaatWidth - STELRUIMTE;
+ const frameOuterHeight = sparingsmaatHeight - STELRUIMTE / 2; // 5mm top tolerance only
+ const doorLeafWidth = frameOuterWidth - (2 * HANGNAAD);
+ const doorLeafHeight = frameOuterHeight - (2 * HANGNAAD);
+
+ return {
+ sparingsmaatWidth,
+ sparingsmaatHeight,
+ frameOuterWidth,
+ frameOuterHeight,
+ doorLeafWidth,
+ doorLeafHeight,
+ stelruimtePerSide: STELRUIMTE / 2, // 5mm gap visible on each side
+ hangnaadPerSide: HANGNAAD, // 3mm gap between frame and leaf
+ };
+}
+
// ============================================
// PHYSICAL PART TYPES
// ============================================