gladiopeace commited on
Commit
60bd933
·
verified ·
1 Parent(s): 8a04652

Add 1 files

Browse files
Files changed (1) hide show
  1. index.html +125 -67
index.html CHANGED
@@ -383,6 +383,14 @@
383
  scene.add(cabinetGroup);
384
  updateCabinetModel();
385
 
 
 
 
 
 
 
 
 
386
  // Handle window resize
387
  window.addEventListener('resize', onWindowResize);
388
 
@@ -421,6 +429,7 @@
421
  const shelvesCount = parseInt(shelvesSlider.value);
422
  const drawersCount = cabinetType.value === 'base' ? parseInt(drawersSlider.value) : 0;
423
  const hasGlassDoors = glassDoors.checked;
 
424
 
425
  // Set main material
426
  let mainMaterial = createMaterial(colorValue, false);
@@ -435,77 +444,91 @@
435
  metalness: 0.0
436
  });
437
 
438
- // Cabinet dimensions
439
- const thickness = 0.75;
440
- const doorThickness = 1.0;
441
- const handleSize = 0.2;
442
  const shelfThickness = 0.5;
443
 
 
 
 
 
444
  // Bottom panel
445
  createPanel(width, thickness, depth,
446
  [0, thickness/2, 0],
447
- mainMaterial);
448
 
449
  // Top panel
450
  createPanel(width, thickness, depth,
451
  [0, height - thickness/2, 0],
452
- mainMaterial);
453
 
454
  // Left side
455
  createPanel(thickness, height - 2*thickness, depth,
456
  [-width/2 + thickness/2, height/2, 0],
457
- mainMaterial);
458
 
459
  // Right side
460
  createPanel(thickness, height - 2*thickness, depth,
461
  [width/2 - thickness/2, height/2, 0],
462
- mainMaterial);
463
 
464
  // Back panel
465
  createPanel(width - 2*thickness, height - 2*thickness, thickness,
466
  [0, height/2, -depth/2 + thickness/2],
467
- mainMaterial);
 
 
 
468
 
469
- // Middle divider if two doors
470
  if (isTwoDoors) {
471
- createPanel(thickness, height - 2*thickness - (drawersCount > 0 ? (height * 0.33) : 0), depth,
472
- [0, height/2 - (drawersCount > 0 ? (height * 0.33)/2 : 0), 0],
473
- mainMaterial);
 
474
  }
475
 
476
  // Create doors
477
- const doorHeight = height - thickness - (drawersCount > 0 ? (height * 0.33) : 0);
478
- const doorYPosition = height/2 - (drawersCount > 0 ? (height * 0.33)/2 : 0);
479
 
480
  if (isTwoDoors) {
481
  const doorWidth = (width - thickness) / 2;
482
 
483
  // Left door
484
  createDoor(doorWidth, doorHeight, doorThickness,
485
- [-(width - doorWidth)/2 + doorThickness/2, doorYPosition, depth/2 - doorThickness/2],
486
- mainMaterial, hasGlassDoors, true);
487
 
488
  // Right door
489
  createDoor(doorWidth, doorHeight, doorThickness,
490
- [(width - doorWidth)/2 - doorThickness/2, doorYPosition, depth/2 - doorThickness/2],
491
- mainMaterial, hasGlassDoors, false);
492
  } else {
493
  // Single door
494
  const doorWidth = width;
495
  createDoor(doorWidth, doorHeight, doorThickness,
496
  [0, doorYPosition, depth/2 - doorThickness/2],
497
- mainMaterial, hasGlassDoors, false);
498
  }
499
 
500
- // Add shelves
501
- const availableHeight = height - 2*thickness - (drawersCount > 0 ? (height * 0.33) : 0);
502
  const shelfSpacing = availableHeight / (shelvesCount + 1);
503
 
504
  for (let i = 0; i < shelvesCount; i++) {
505
- const shelfY = thickness + (i + 1) * shelfSpacing - (drawersCount > 0 ? (height * 0.33)/2 : 0);
 
 
 
 
 
 
506
  createShelf(width - 2*thickness - 0.5, shelfThickness, depth - thickness - 0.5,
507
- [0, shelfY, -0.25],
508
- shelfMaterial);
509
  }
510
 
511
  // Add drawers for base cabinets
@@ -515,19 +538,19 @@
515
 
516
  for (let i = 0; i < drawersCount; i++) {
517
  const drawerY = thickness + i * drawerHeight + drawerHeight/2;
518
- createDrawer(width, drawerHeight, depth * 0.7,
519
- [0, drawerY, depth/4 - depth/8],
520
- drawerFrontMaterial, mainMaterial);
521
  }
522
  }
523
 
524
  // Adjust camera target based on cabinet size
525
  controls.target.set(0, height/2, 0);
526
  controls.update();
 
527
 
528
  // Update capacity calculation
529
  const interiorWidth = width - 2*thickness;
530
- const interiorHeight = height - 2*thickness - (drawersCount > 0 ? (height * 0.33) : 0);
531
  const interiorDepth = depth - thickness;
532
  const capacity = (interiorWidth * interiorHeight * interiorDepth) / 1728; // convert to cubic feet
533
 
@@ -538,6 +561,9 @@
538
  capacityDisplay.textContent = `${capacity.toFixed(1)} cu.ft`;
539
  dimensionsDisplay.textContent = `${width}" W × ${height}" H × ${depth}" D`;
540
  shelvesDisplay.textContent = shelvesCount;
 
 
 
541
  }
542
 
543
  function createMaterial(colorValue, isDrawerFront = false) {
@@ -584,17 +610,17 @@
584
  return new THREE.MeshStandardMaterial(materialOptions);
585
  }
586
 
587
- function createPanel(width, height, depth, position, material) {
588
  const geometry = new THREE.BoxGeometry(width, height, depth);
589
  const panel = new THREE.Mesh(geometry, material);
590
  panel.castShadow = true;
591
  panel.receiveShadow = true;
592
  panel.position.set(position[0], position[1], position[2]);
593
- cabinetGroup.add(panel);
594
  return panel;
595
  }
596
 
597
- function createDoor(width, height, thickness, position, material, hasGlass, isLeftDoor) {
598
  const doorGroup = new THREE.Group();
599
  doorGroup.position.set(position[0], position[1], position[2]);
600
 
@@ -607,37 +633,53 @@
607
 
608
  // Glass panel if selected
609
  if (hasGlass) {
610
- const glassWidth = width * 0.8;
611
- const glassHeight = height * 0.7;
612
- const glassGeometry = new THREE.BoxGeometry(glassWidth, glassHeight, thickness * 0.1);
613
  const glassMaterial = new THREE.MeshPhysicalMaterial({
614
- color: 0x88ccff,
615
- transmission: 0.8,
616
- roughness: 0.1,
617
  metalness: 0.0,
618
  transparent: true,
619
- opacity: 0.7,
620
  ior: 1.5,
621
  thickness: 0.1
622
  });
623
  const glass = new THREE.Mesh(glassGeometry, glassMaterial);
624
- glass.position.z = thickness * 0.45;
625
  doorGroup.add(glass);
626
  }
627
 
628
  // Handle
629
- const handleGeometry = new THREE.CylinderGeometry(0.15, 0.15, 3, 16);
630
  const handleMaterial = new THREE.MeshStandardMaterial({ color: 0x333333 });
631
  const handle = new THREE.Mesh(handleGeometry, handleMaterial);
632
  handle.rotation.z = Math.PI/2;
633
  handle.position.set(isLeftDoor ? -width/2 + 2 : width/2 - 2, 0, thickness);
634
  doorGroup.add(handle);
635
 
636
- cabinetGroup.add(doorGroup);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
637
  return doorGroup;
638
  }
639
 
640
- function createShelf(width, thickness, depth, position, material) {
641
  const shelfGroup = new THREE.Group();
642
  shelfGroup.position.set(position[0], position[1], position[2]);
643
 
@@ -649,79 +691,94 @@
649
  shelfGroup.add(shelf);
650
 
651
  // Shelf supports
652
- const supportGeometry = new THREE.BoxGeometry(0.5, 1, 0.5);
653
  const supportMaterial = new THREE.MeshStandardMaterial({ color: 0xCCCCCC });
654
 
655
  // Left support
656
  const leftSupport = new THREE.Mesh(supportGeometry, supportMaterial);
657
- leftSupport.position.set(-width/2 + 0.25, -thickness/2 - 0.5, -depth/2 + 0.25);
658
  shelfGroup.add(leftSupport);
659
 
660
  // Right support
661
  const rightSupport = new THREE.Mesh(supportGeometry, supportMaterial);
662
- rightSupport.position.set(width/2 - 0.25, -thickness/2 - 0.5, -depth/2 + 0.25);
663
  shelfGroup.add(rightSupport);
664
 
665
  if (width > 24) {
666
  // Middle support for wider shelves
667
  const midSupport = new THREE.Mesh(supportGeometry, supportMaterial);
668
- midSupport.position.set(0, -thickness/2 - 0.5, -depth/2 + 0.25);
669
  shelfGroup.add(midSupport);
670
  }
671
 
672
- cabinetGroup.add(shelfGroup);
673
  return shelfGroup;
674
  }
675
 
676
- function createDrawer(width, height, depth, position, frontMaterial, sideMaterial) {
677
  const drawerGroup = new THREE.Group();
678
  drawerGroup.position.set(position[0], position[1], position[2]);
679
 
680
- // Drawer box
681
- const boxHeight = height * 0.9;
682
- const boxYOffset = -height * 0.05;
 
683
 
684
  // Front
685
- const frontGeometry = new THREE.BoxGeometry(width * 0.9, height * 0.95, depth * 0.1);
686
  const front = new THREE.Mesh(frontGeometry, frontMaterial);
687
- front.position.set(0, boxYOffset, depth * 0.35);
688
  drawerGroup.add(front);
689
 
690
  // Bottom
691
- const bottomGeometry = new THREE.BoxGeometry(width * 0.85, 0.2, depth * 0.8);
692
  const bottom = new THREE.Mesh(bottomGeometry, sideMaterial);
693
- bottom.position.set(0, boxYOffset - boxHeight/2 + 0.1, 0);
694
  drawerGroup.add(bottom);
695
 
696
  // Sides
697
- const sideWidth = width * 0.85;
698
- const sideGeometry = new THREE.BoxGeometry(0.2, boxHeight, depth * 0.8);
699
 
700
  // Left side
701
  const leftSide = new THREE.Mesh(sideGeometry, sideMaterial);
702
- leftSide.position.set(-sideWidth/2, boxYOffset, 0);
703
  drawerGroup.add(leftSide);
704
 
705
  // Right side
706
  const rightSide = new THREE.Mesh(sideGeometry, sideMaterial);
707
- rightSide.position.set(sideWidth/2, boxYOffset, 0);
708
  drawerGroup.add(rightSide);
709
 
710
  // Back
711
- const backGeometry = new THREE.BoxGeometry(sideWidth, boxHeight, 0.2);
712
  const back = new THREE.Mesh(backGeometry, sideMaterial);
713
- back.position.set(0, boxYOffset, depth * -0.3);
714
  drawerGroup.add(back);
715
 
716
- // Handle (simplified as a bar)
717
- const handleGeometry = new THREE.CylinderGeometry(0.1, 0.1, 4, 16);
718
  const handleMaterial = new THREE.MeshStandardMaterial({ color: 0x333333 });
719
  const handle = new THREE.Mesh(handleGeometry, handleMaterial);
720
  handle.rotation.z = Math.PI/2;
721
- handle.position.set(0, boxYOffset, depth * 0.35 + 0.1);
722
  drawerGroup.add(handle);
723
 
724
- cabinetGroup.add(drawerGroup);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
725
  return drawerGroup;
726
  }
727
 
@@ -729,6 +786,7 @@
729
  loadingOverlay.style.opacity = 1;
730
  loadingOverlay.style.pointerEvents = 'auto';
731
  let progress = 0;
 
732
  const interval = setInterval(() => {
733
  progress += 10;
734
  const offset = 314 * (1 - progress/100);
@@ -736,7 +794,7 @@
736
  if (progress >= 100) {
737
  clearInterval(interval);
738
  }
739
- }, 30);
740
  }
741
 
742
  function hideLoading() {
 
383
  scene.add(cabinetGroup);
384
  updateCabinetModel();
385
 
386
+ // Add a grid helper and axes helper for debugging (can be removed in production)
387
+ const gridHelper = new THREE.GridHelper(100, 100);
388
+ scene.add(gridHelper);
389
+
390
+ const axesHelper = new THREE.AxesHelper(5);
391
+ axesHelper.position.y = 0.1; // Slightly above ground
392
+ scene.add(axesHelper);
393
+
394
  // Handle window resize
395
  window.addEventListener('resize', onWindowResize);
396
 
 
429
  const shelvesCount = parseInt(shelvesSlider.value);
430
  const drawersCount = cabinetType.value === 'base' ? parseInt(drawersSlider.value) : 0;
431
  const hasGlassDoors = glassDoors.checked;
432
+ const thickness = 0.75; // Material thickness in inches
433
 
434
  // Set main material
435
  let mainMaterial = createMaterial(colorValue, false);
 
444
  metalness: 0.0
445
  });
446
 
447
+ // These factors help with converting inches to Three.js units
448
+ // Since Three.js uses arbitrary units, we'll treat 1 unit = 1 inch
449
+ const doorThickness = 0.75;
450
+ const handleSize = 2.0; // Door handle size
451
  const shelfThickness = 0.5;
452
 
453
+ // Create the cabinet box structure first
454
+ let cabinetBox = new THREE.Group();
455
+ cabinetGroup.add(cabinetBox);
456
+
457
  // Bottom panel
458
  createPanel(width, thickness, depth,
459
  [0, thickness/2, 0],
460
+ mainMaterial, cabinetBox);
461
 
462
  // Top panel
463
  createPanel(width, thickness, depth,
464
  [0, height - thickness/2, 0],
465
+ mainMaterial, cabinetBox);
466
 
467
  // Left side
468
  createPanel(thickness, height - 2*thickness, depth,
469
  [-width/2 + thickness/2, height/2, 0],
470
+ mainMaterial, cabinetBox);
471
 
472
  // Right side
473
  createPanel(thickness, height - 2*thickness, depth,
474
  [width/2 - thickness/2, height/2, 0],
475
+ mainMaterial, cabinetBox);
476
 
477
  // Back panel
478
  createPanel(width - 2*thickness, height - 2*thickness, thickness,
479
  [0, height/2, -depth/2 + thickness/2],
480
+ mainMaterial, cabinetBox);
481
+
482
+ // Calculate interior height (accounting for drawers if they exist)
483
+ const interiorHeight = height - 2*thickness - (drawersCount > 0 ? (height * 0.33) : 0);
484
 
485
+ // Middle divider if two doors (only extends down to drawer section if drawers exist)
486
  if (isTwoDoors) {
487
+ const dividerHeight = drawersCount > 0 ? height - 2*thickness - (height * 0.33) : height - 2*thickness;
488
+ createPanel(thickness, dividerHeight, depth,
489
+ [0, (drawersCount > 0 ? (height/2 - (height * 0.33)/2) : height/2), 0],
490
+ mainMaterial, cabinetBox);
491
  }
492
 
493
  // Create doors
494
+ const doorHeight = drawersCount > 0 ? height - thickness - (height * 0.33) : height - 2*thickness;
495
+ const doorYPosition = drawersCount > 0 ? height/2 - (height * 0.33)/2 : height/2;
496
 
497
  if (isTwoDoors) {
498
  const doorWidth = (width - thickness) / 2;
499
 
500
  // Left door
501
  createDoor(doorWidth, doorHeight, doorThickness,
502
+ [-(width - thickness)/2 + doorThickness/2, doorYPosition, depth/2 - doorThickness/2],
503
+ mainMaterial, hasGlassDoors, true, cabinetBox);
504
 
505
  // Right door
506
  createDoor(doorWidth, doorHeight, doorThickness,
507
+ [(width - thickness)/2 - doorThickness/2, doorYPosition, depth/2 - doorThickness/2],
508
+ mainMaterial, hasGlassDoors, false, cabinetBox);
509
  } else {
510
  // Single door
511
  const doorWidth = width;
512
  createDoor(doorWidth, doorHeight, doorThickness,
513
  [0, doorYPosition, depth/2 - doorThickness/2],
514
+ mainMaterial, hasGlassDoors, false, cabinetBox);
515
  }
516
 
517
+ // Add shelves only in the upper section (above any drawers)
518
+ const availableHeight = interiorHeight;
519
  const shelfSpacing = availableHeight / (shelvesCount + 1);
520
 
521
  for (let i = 0; i < shelvesCount; i++) {
522
+ const shelfY = thickness + (i + 1) * shelfSpacing;
523
+ if (drawersCount > 0) {
524
+ // Adjust shelf position to be above the drawer section
525
+ const drawerSectionHeight = height * 0.33;
526
+ shelfY = thickness + (i + 1) * shelfSpacing + (height - thickness - drawerSectionHeight - availableHeight);
527
+ }
528
+
529
  createShelf(width - 2*thickness - 0.5, shelfThickness, depth - thickness - 0.5,
530
+ [0, shelfY, 0],
531
+ shelfMaterial, cabinetBox);
532
  }
533
 
534
  // Add drawers for base cabinets
 
538
 
539
  for (let i = 0; i < drawersCount; i++) {
540
  const drawerY = thickness + i * drawerHeight + drawerHeight/2;
541
+ createDrawer(width, drawerHeight, depth * 0.8,
542
+ [0, drawerY, depth/2 - depth*0.1],
543
+ drawerFrontMaterial, mainMaterial, cabinetBox);
544
  }
545
  }
546
 
547
  // Adjust camera target based on cabinet size
548
  controls.target.set(0, height/2, 0);
549
  controls.update();
550
+ camera.position.set(width * 1.2, height * 1.2, depth * 1.2);
551
 
552
  // Update capacity calculation
553
  const interiorWidth = width - 2*thickness;
 
554
  const interiorDepth = depth - thickness;
555
  const capacity = (interiorWidth * interiorHeight * interiorDepth) / 1728; // convert to cubic feet
556
 
 
561
  capacityDisplay.textContent = `${capacity.toFixed(1)} cu.ft`;
562
  dimensionsDisplay.textContent = `${width}" W × ${height}" H × ${depth}" D`;
563
  shelvesDisplay.textContent = shelvesCount;
564
+ if (drawersCount > 0) {
565
+ drawersDisplay.textContent = drawersCount;
566
+ }
567
  }
568
 
569
  function createMaterial(colorValue, isDrawerFront = false) {
 
610
  return new THREE.MeshStandardMaterial(materialOptions);
611
  }
612
 
613
+ function createPanel(width, height, depth, position, material, parentGroup) {
614
  const geometry = new THREE.BoxGeometry(width, height, depth);
615
  const panel = new THREE.Mesh(geometry, material);
616
  panel.castShadow = true;
617
  panel.receiveShadow = true;
618
  panel.position.set(position[0], position[1], position[2]);
619
+ parentGroup.add(panel);
620
  return panel;
621
  }
622
 
623
+ function createDoor(width, height, thickness, position, material, hasGlass, isLeftDoor, parentGroup) {
624
  const doorGroup = new THREE.Group();
625
  doorGroup.position.set(position[0], position[1], position[2]);
626
 
 
633
 
634
  // Glass panel if selected
635
  if (hasGlass) {
636
+ const glassWidth = width * 0.9;
637
+ const glassHeight = height * 0.8;
638
+ const glassGeometry = new THREE.BoxGeometry(glassWidth, glassHeight, thickness * 0.05);
639
  const glassMaterial = new THREE.MeshPhysicalMaterial({
640
+ color: 0xE6F0FF,
641
+ transmission: 0.9,
642
+ roughness: 0.0,
643
  metalness: 0.0,
644
  transparent: true,
645
+ opacity: 0.8,
646
  ior: 1.5,
647
  thickness: 0.1
648
  });
649
  const glass = new THREE.Mesh(glassGeometry, glassMaterial);
650
+ glass.position.z = thickness * 0.3;
651
  doorGroup.add(glass);
652
  }
653
 
654
  // Handle
655
+ const handleGeometry = new THREE.CylinderGeometry(0.5, 0.5, 3, 16);
656
  const handleMaterial = new THREE.MeshStandardMaterial({ color: 0x333333 });
657
  const handle = new THREE.Mesh(handleGeometry, handleMaterial);
658
  handle.rotation.z = Math.PI/2;
659
  handle.position.set(isLeftDoor ? -width/2 + 2 : width/2 - 2, 0, thickness);
660
  doorGroup.add(handle);
661
 
662
+ // Hinges (simple representation)
663
+ const hingeGeometry = new THREE.CylinderGeometry(0.2, 0.2, 0.5, 16);
664
+ const hingeMaterial = new THREE.MeshStandardMaterial({ color: 0x888888 });
665
+
666
+ // Top hinge
667
+ const topHinge = new THREE.Mesh(hingeGeometry, hingeMaterial);
668
+ topHinge.rotation.x = Math.PI/2;
669
+ topHinge.position.set(isLeftDoor ? width/2 - 1 : -width/2 + 1, height/2 - 2, -thickness/2);
670
+ doorGroup.add(topHinge);
671
+
672
+ // Bottom hinge
673
+ const bottomHinge = new THREE.Mesh(hingeGeometry, hingeMaterial);
674
+ bottomHinge.rotation.x = Math.PI/2;
675
+ bottomHinge.position.set(isLeftDoor ? width/2 - 1 : -width/2 + 1, -height/2 + 2, -thickness/2);
676
+ doorGroup.add(bottomHinge);
677
+
678
+ parentGroup.add(doorGroup);
679
  return doorGroup;
680
  }
681
 
682
+ function createShelf(width, thickness, depth, position, material, parentGroup) {
683
  const shelfGroup = new THREE.Group();
684
  shelfGroup.position.set(position[0], position[1], position[2]);
685
 
 
691
  shelfGroup.add(shelf);
692
 
693
  // Shelf supports
694
+ const supportGeometry = new THREE.BoxGeometry(0.5, 1.5, 0.5);
695
  const supportMaterial = new THREE.MeshStandardMaterial({ color: 0xCCCCCC });
696
 
697
  // Left support
698
  const leftSupport = new THREE.Mesh(supportGeometry, supportMaterial);
699
+ leftSupport.position.set(-width/2 + 0.25, -thickness/2 - 0.75, 0);
700
  shelfGroup.add(leftSupport);
701
 
702
  // Right support
703
  const rightSupport = new THREE.Mesh(supportGeometry, supportMaterial);
704
+ rightSupport.position.set(width/2 - 0.25, -thickness/2 - 0.75, 0);
705
  shelfGroup.add(rightSupport);
706
 
707
  if (width > 24) {
708
  // Middle support for wider shelves
709
  const midSupport = new THREE.Mesh(supportGeometry, supportMaterial);
710
+ midSupport.position.set(0, -thickness/2 - 0.75, 0);
711
  shelfGroup.add(midSupport);
712
  }
713
 
714
+ parentGroup.add(shelfGroup);
715
  return shelfGroup;
716
  }
717
 
718
+ function createDrawer(width, height, depth, position, frontMaterial, sideMaterial, parentGroup) {
719
  const drawerGroup = new THREE.Group();
720
  drawerGroup.position.set(position[0], position[1], position[2]);
721
 
722
+ // Drawer body
723
+ const bodyWidth = width * 0.9;
724
+ const bodyHeight = height * 0.85;
725
+ const bodyDepth = depth;
726
 
727
  // Front
728
+ const frontGeometry = new THREE.BoxGeometry(width, height, 0.5);
729
  const front = new THREE.Mesh(frontGeometry, frontMaterial);
730
+ front.position.set(0, 0, depth/2 + 0.25);
731
  drawerGroup.add(front);
732
 
733
  // Bottom
734
+ const bottomGeometry = new THREE.BoxGeometry(width * 0.9, 0.2, depth);
735
  const bottom = new THREE.Mesh(bottomGeometry, sideMaterial);
736
+ bottom.position.set(0, -height/2 + 0.1, 0);
737
  drawerGroup.add(bottom);
738
 
739
  // Sides
740
+ const sideWidth = width * 0.9;
741
+ const sideGeometry = new THREE.BoxGeometry(0.2, bodyHeight, depth);
742
 
743
  // Left side
744
  const leftSide = new THREE.Mesh(sideGeometry, sideMaterial);
745
+ leftSide.position.set(-sideWidth/2, 0, 0);
746
  drawerGroup.add(leftSide);
747
 
748
  // Right side
749
  const rightSide = new THREE.Mesh(sideGeometry, sideMaterial);
750
+ rightSide.position.set(sideWidth/2, 0, 0);
751
  drawerGroup.add(rightSide);
752
 
753
  // Back
754
+ const backGeometry = new THREE.BoxGeometry(sideWidth, bodyHeight, 0.2);
755
  const back = new THREE.Mesh(backGeometry, sideMaterial);
756
+ back.position.set(0, 0, -depth/2 + 0.1);
757
  drawerGroup.add(back);
758
 
759
+ // Handle (as a bar)
760
+ const handleGeometry = new THREE.CylinderGeometry(0.3, 0.3, 3, 16);
761
  const handleMaterial = new THREE.MeshStandardMaterial({ color: 0x333333 });
762
  const handle = new THREE.Mesh(handleGeometry, handleMaterial);
763
  handle.rotation.z = Math.PI/2;
764
+ handle.position.set(0, 0, depth/2 + 0.3);
765
  drawerGroup.add(handle);
766
 
767
+ // Drawer slides
768
+ const slideGeometry = new THREE.BoxGeometry(0.1, 0.5, depth * 1.2);
769
+ const slideMaterial = new THREE.MeshStandardMaterial({ color: 0x888888 });
770
+
771
+ // Left slide
772
+ const leftSlide = new THREE.Mesh(slideGeometry, slideMaterial);
773
+ leftSlide.position.set(-width/2 + 0.25, -height/2 + 0.25, 0);
774
+ drawerGroup.add(leftSlide);
775
+
776
+ // Right slide
777
+ const rightSlide = new THREE.Mesh(slideGeometry, slideMaterial);
778
+ rightSlide.position.set(width/2 - 0.25, -height/2 + 0.25, 0);
779
+ drawerGroup.add(rightSlide);
780
+
781
+ parentGroup.add(drawerGroup);
782
  return drawerGroup;
783
  }
784
 
 
786
  loadingOverlay.style.opacity = 1;
787
  loadingOverlay.style.pointerEvents = 'auto';
788
  let progress = 0;
789
+ progressRing.style.strokeDashoffset = 314;
790
  const interval = setInterval(() => {
791
  progress += 10;
792
  const offset = 314 * (1 - progress/100);
 
794
  if (progress >= 100) {
795
  clearInterval(interval);
796
  }
797
+ }, 50);
798
  }
799
 
800
  function hideLoading() {