"use client";
import { Canvas } from "@react-three/fiber";
import {
OrbitControls,
PerspectiveCamera,
Environment,
ContactShadows,
RoundedBox,
} from "@react-three/drei";
import { Door3DEnhanced } from "./door-3d-enhanced";
import { useConfiguratorStore } from "@/lib/store";
import {
STELRUIMTE,
WALL_THICKNESS,
mmToMeters,
} from "@/lib/door-models";
import * as THREE from "three";
// ============================================
// MATERIALS
// ============================================
const WallMaterial = () => (
);
const RevealMaterial = () => (
);
const FloorMaterial = () => (
);
const WoodMaterial = () => (
);
const DarkMetalMaterial = () => (
);
// ============================================
// WALL CONTAINER WITH PRECISE HOLE
// ============================================
function WallContainer({
holeWidth,
holeHeight,
wallThickness,
}: {
holeWidth: number;
holeHeight: number;
wallThickness: number;
}) {
const wallWidth = 4.0;
const wallHeight = 3.0;
const halfHoleW = holeWidth / 2;
const halfWallT = wallThickness / 2;
const leftSectionWidth = (wallWidth - holeWidth) / 2;
const leftSectionX = -(halfHoleW + leftSectionWidth / 2);
const rightSectionWidth = leftSectionWidth;
const rightSectionX = halfHoleW + rightSectionWidth / 2;
const topSectionHeight = wallHeight - holeHeight;
const topSectionY = holeHeight + topSectionHeight / 2;
const gapPerSide = mmToMeters(STELRUIMTE / 2);
return (
{/* Main wall sections */}
{topSectionHeight > 0.01 && (
)}
{/* Reveal surfaces */}
{/* Reveal depth surfaces */}
{/* Baseboard - front side */}
);
}
// ============================================
// ROOM STRUCTURE
// ============================================
function RoomShell() {
const wallHeight = 3.0;
const roomDepth = 3.5;
const roomWidth = 7.0; // Much wider than the 4m back wall
const sideWallThickness = 0.08;
const floorSize = 10;
return (
{/* Front floor (viewer side) */}
{/* Back floor (behind wall) */}
{/* Floor plank lines (viewer side) */}
{Array.from({ length: 20 }).map((_, i) => {
const x = -2.7 + i * 0.27;
return (
);
})}
{/* Left side wall */}
{/* Right side wall */}
{/* Left side baseboard */}
{/* Right side baseboard */}
{/* Ceiling (partial - hint near the wall) */}
{/* Back room - bedroom visible through glass door */}
);
}
// ============================================
// BEDROOM (visible through the glass door)
// ============================================
function Bedroom() {
const wallWidth = 4.0;
const wallHeight = 3.0;
const roomDepth = 4.0;
const backZ = -roomDepth;
return (
{/* Back wall */}
{/* Left side wall (bedroom) */}
{/* Right side wall (bedroom) */}
{/* Bedroom ceiling */}
{/* Bedroom baseboard - back wall */}
{/* Bedroom baseboard - left */}
{/* Bedroom baseboard - right */}
{/* Window on back wall (bright rectangle suggesting daylight) */}
{/* Window frame */}
{[
{ pos: [0, 2.1, backZ + 0.015] as [number, number, number], size: [1.26, 0.03, 0.02] as [number, number, number] },
{ pos: [0, 1.1, backZ + 0.015] as [number, number, number], size: [1.26, 0.03, 0.02] as [number, number, number] },
{ pos: [-0.615, 1.6, backZ + 0.015] as [number, number, number], size: [0.03, 1.06, 0.02] as [number, number, number] },
{ pos: [0.615, 1.6, backZ + 0.015] as [number, number, number], size: [0.03, 1.06, 0.02] as [number, number, number] },
{ pos: [0, 1.6, backZ + 0.015] as [number, number, number], size: [0.02, 1.0, 0.02] as [number, number, number] },
{ pos: [0, 1.6, backZ + 0.015] as [number, number, number], size: [1.2, 0.02, 0.02] as [number, number, number] },
].map((f, i) => (
))}
{/* Window light */}
{/* === BED === */}
{/* Bed frame base */}
{/* Mattress */}
{/* Duvet/blanket */}
{/* Duvet fold at top */}
{/* Pillows */}
{/* Headboard */}
{/* Bed legs (metal) */}
{[
[-0.72, 0, -0.97],
[0.72, 0, -0.97],
[-0.72, 0, 0.97],
[0.72, 0, 0.97],
].map(([x, _, z], i) => (
))}
{/* === NIGHTSTAND LEFT === */}
{/* Legs */}
{[[-0.17, -0.14], [0.17, -0.14], [-0.17, 0.14], [0.17, 0.14]].map(([x, z], i) => (
))}
{/* Lamp on nightstand */}
{/* === NIGHTSTAND RIGHT === */}
{[[-0.17, -0.14], [0.17, -0.14], [-0.17, 0.14], [0.17, 0.14]].map(([x, z], i) => (
))}
{/* Small plant on nightstand */}
{/* === BEDROOM RUG === */}
{/* === CEILING LIGHT (bedroom) === */}
{/* === WALL ART (bedroom back wall) === */}
{/* Simple abstract circle */}
{/* Frame */}
{[
[0, 0.225, 0.35, 0.02],
[0, -0.225, 0.35, 0.02],
[-0.175, 0, 0.02, 0.45],
[0.175, 0, 0.02, 0.45],
].map(([x, y, w, h], i) => (
))}
{/* Second art piece */}
{[
[0, 0.2, 0.3, 0.02],
[0, -0.2, 0.3, 0.02],
[-0.15, 0, 0.02, 0.4],
[0.15, 0, 0.02, 0.4],
].map(([x, y, w, h], i) => (
))}
);
}
// ============================================
// FURNITURE: SIDEBOARD
// ============================================
function Sideboard() {
const bodyW = 0.9;
const bodyH = 0.44;
const bodyD = 0.36;
const legH = 0.12;
const yBody = legH + bodyH / 2;
const wallFaceZ = 0.075; // Front face of main wall
return (
{/* Body */}
{/* Top surface (darker edge) */}
{/* Metal legs */}
{[
[-bodyW / 2 + 0.06, 0, -bodyD / 2 + 0.06],
[bodyW / 2 - 0.06, 0, -bodyD / 2 + 0.06],
[-bodyW / 2 + 0.06, 0, bodyD / 2 - 0.06],
[bodyW / 2 - 0.06, 0, bodyD / 2 - 0.06],
].map(([x, _, z], i) => (
))}
{/* Drawer line (decorative) */}
);
}
// ============================================
// FURNITURE: DECORATIVE OBJECTS
// ============================================
function VaseWithBranches() {
const wallFaceZ = 0.075;
return (
{/* Vase body */}
{/* Vase neck */}
{/* Rim */}
{/* Dried branches */}
{[
{ rot: [0.2, 0, 0.1] as [number, number, number], h: 0.3 },
{ rot: [-0.15, 1.2, -0.1] as [number, number, number], h: 0.28 },
{ rot: [0.1, 2.5, 0.2] as [number, number, number], h: 0.25 },
].map((branch, i) => (
))}
);
}
function BookStack() {
const wallFaceZ = 0.075;
return (
{[
{ w: 0.15, h: 0.022, d: 0.1, color: "#2c3e50", y: 0 },
{ w: 0.14, h: 0.018, d: 0.1, color: "#7f8c8d", y: 0.02 },
{ w: 0.13, h: 0.016, d: 0.1, color: "#8e4a3b", y: 0.037 },
].map((book, i) => (
))}
);
}
// ============================================
// FURNITURE: TALL PLANT
// ============================================
function TallPlant() {
const wallFaceZ = 0.075;
return (
{/* Pot */}
{/* Pot rim */}
{/* Soil */}
{/* Trunk */}
{/* Secondary trunk */}
{/* Foliage clusters */}
{[
[0, 0.92, 0, 0.14],
[0.08, 0.84, 0.04, 0.11],
[-0.07, 0.86, -0.03, 0.10],
[0.04, 0.78, -0.06, 0.09],
[-0.03, 0.97, 0.03, 0.10],
[0.1, 0.72, 0.02, 0.08],
[-0.05, 0.76, 0.05, 0.08],
].map(([x, y, z, r], i) => (
))}
);
}
// ============================================
// FURNITURE: PENDANT LIGHT
// ============================================
function PendantLight() {
return (
{/* Cord */}
{/* Canopy (ceiling mount) */}
{/* Shade - open bottom */}
{/* Shade rim */}
{/* Warm point light (simulates bulb glow) */}
);
}
// ============================================
// FURNITURE: PICTURE FRAME
// ============================================
function PictureFrame() {
const frameW = 0.45;
const frameH = 0.55;
const border = 0.025;
const wallFaceZ = 0.076;
return (
{/* Canvas/art (abstract warm tones) */}
{/* Abstract shape 1 */}
{/* Abstract shape 2 */}
{/* Frame border */}
{[
{ pos: [0, frameH / 2 - border / 2, 0.005] as [number, number, number], size: [frameW, border, 0.018] as [number, number, number] },
{ pos: [0, -frameH / 2 + border / 2, 0.005] as [number, number, number], size: [frameW, border, 0.018] as [number, number, number] },
{ pos: [-frameW / 2 + border / 2, 0, 0.005] as [number, number, number], size: [border, frameH, 0.018] as [number, number, number] },
{ pos: [frameW / 2 - border / 2, 0, 0.005] as [number, number, number], size: [border, frameH, 0.018] as [number, number, number] },
].map((side, i) => (
))}
);
}
// ============================================
// FURNITURE: RUG
// ============================================
function Rug() {
return (
);
}
// ============================================
// FURNITURE: SMALL SIDE TABLE (right side)
// ============================================
function SideTable() {
const wallFaceZ = 0.075;
const tableR = 0.18;
const tableH = 0.5;
return (
{/* Tabletop */}
{/* Single leg */}
{/* Base */}
{/* Small decorative candle */}
);
}
// ============================================
// DOOR + WALL COMPOSITION
// ============================================
/**
* Side panel: a fixed glass panel with steel frame, rendered next to the door.
*/
function SidePanelMesh({
panelWidth,
panelHeight,
finish,
glassColor,
}: {
panelWidth: number; // meters
panelHeight: number; // meters
finish: import("@/lib/store").Finish;
glassColor: import("@/lib/store").GlassColor;
}) {
const profileW = mmToMeters(40);
const profileD = mmToMeters(40);
const glassThick = mmToMeters(7);
const FRAME_COLORS_LOCAL: Record = {
zwart: "#1a1a1a", brons: "#8B6F47", grijs: "#525252",
goud: "#B8860B", beige: "#C8B88A", ral: "#4A6741",
};
const GLASS_COLORS_LOCAL: Record = {
helder: { color: "#eff6ff", transmission: 0.98, roughness: 0.05 },
grijs: { color: "#3a3a3a", transmission: 0.85, roughness: 0.1 },
brons: { color: "#8B6F47", transmission: 0.85, roughness: 0.1 },
"mat-blank": { color: "#e8e8e8", transmission: 0.7, roughness: 0.3 },
"mat-brons": { color: "#A0845C", transmission: 0.6, roughness: 0.35 },
"mat-zwart": { color: "#1a1a1a", transmission: 0.5, roughness: 0.4 },
};
const frameColor = FRAME_COLORS_LOCAL[finish] || "#1a1a1a";
const glassProps = GLASS_COLORS_LOCAL[glassColor] || GLASS_COLORS_LOCAL.helder;
const innerW = panelWidth - profileW * 2;
const innerH = panelHeight - profileW * 2;
return (
{/* Left stile */}
{/* Right stile */}
{/* Top rail */}
{/* Bottom rail */}
{/* Glass */}
);
}
function DoorInWall() {
const { doorType, doorConfig, sidePanel, doorLeafWidth, sidePanelWidth, height, finish, glassColor } =
useConfiguratorStore();
const doorWidthM = mmToMeters(doorLeafWidth);
const doorHeightM = mmToMeters(height);
const wallThicknessM = mmToMeters(WALL_THICKNESS);
const stelruimteM = mmToMeters(STELRUIMTE);
const sidePanelWidthM = mmToMeters(sidePanelWidth);
const isDouble = doorConfig === "dubbele";
// Total door section width (all leaves)
const doorSectionW = isDouble ? doorWidthM * 2 : doorWidthM;
// Total hole width including side panels
let holeWidthM = doorSectionW + stelruimteM;
if (sidePanel === "links" || sidePanel === "rechts") holeWidthM += sidePanelWidthM;
if (sidePanel === "beide") holeWidthM += sidePanelWidthM * 2;
const holeHeightM = doorHeightM + stelruimteM / 2;
const doorZOffset = doorType === "taats" ? 0 : wallThicknessM * 0.15;
// Calculate X offset for the door(s) when side panels shift the center
let doorCenterX = 0;
if (sidePanel === "links") doorCenterX = sidePanelWidthM / 2;
if (sidePanel === "rechts") doorCenterX = -sidePanelWidthM / 2;
return (
<>
{/* Door leaf(s) */}
{isDouble ? (
) : (
)}
{/* Side panels */}
{(sidePanel === "links" || sidePanel === "beide") && sidePanelWidthM > 0 && (
)}
{(sidePanel === "rechts" || sidePanel === "beide") && sidePanelWidthM > 0 && (
)}
>
);
}
// ============================================
// LIGHTING
// ============================================
function Lighting() {
return (
<>
{/* Main sunlight */}
{/* Fill light from behind wall (simulates light from back room) */}
{/* Viewer-side fill to show furniture */}
{/* Top-down for reveal and furniture shadows */}
>
);
}
// ============================================
// MAIN SCENE EXPORT
// ============================================
export function Scene3D() {
return (
);
}