@@ -4,6 +4,7 @@ |
| 4 | import * as THREE from 'three' | 4 | import * as THREE from 'three' |
| 5 | | 5 | |
| 6 | // Create a wooden dock | 6 | // Create a wooden dock |
| | 7 | +// Dock protrudes into water - shore side at origin, water side extends in -Z direction |
| 7 | export function createDock(gradientMap) { | 8 | export function createDock(gradientMap) { |
| 8 | const group = new THREE.Group() | 9 | const group = new THREE.Group() |
| 9 | | 10 | |
@@ -17,39 +18,67 @@ export function createDock(gradientMap) { |
| 17 | gradientMap | 18 | gradientMap |
| 18 | }) | 19 | }) |
| 19 | | 20 | |
| 20 | - // Main platform | 21 | + // Dock dimensions - extends into water |
| 21 | - const platformGeom = new THREE.BoxGeometry(1.2, 0.08, 0.6) | 22 | + const dockWidth = 0.8 |
| | 23 | + const dockLength = 1.2 // How far it protrudes into water |
| | 24 | + const dockHeight = 0.08 |
| | 25 | + |
| | 26 | + // Main platform - offset so shore edge is at z=0, water edge at z=-dockLength |
| | 27 | + const platformGeom = new THREE.BoxGeometry(dockWidth, dockHeight, dockLength) |
| 22 | const platform = new THREE.Mesh(platformGeom, woodMaterial) | 28 | const platform = new THREE.Mesh(platformGeom, woodMaterial) |
| 23 | - platform.position.y = 0.04 | 29 | + platform.position.set(0, 0.04, -dockLength / 2) |
| 24 | group.add(platform) | 30 | group.add(platform) |
| 25 | | 31 | |
| 26 | - // Planks (detail lines) | 32 | + // Planks (crosswise detail lines) |
| 27 | - for (let i = 0; i < 5; i++) { | 33 | + for (let i = 0; i < 6; i++) { |
| 28 | - const plankGeom = new THREE.BoxGeometry(0.02, 0.09, 0.58) | 34 | + const plankGeom = new THREE.BoxGeometry(dockWidth - 0.02, 0.09, 0.03) |
| 29 | const plank = new THREE.Mesh(plankGeom, darkWoodMaterial) | 35 | const plank = new THREE.Mesh(plankGeom, darkWoodMaterial) |
| 30 | - plank.position.set(-0.5 + i * 0.25, 0.045, 0) | 36 | + plank.position.set(0, 0.045, -0.1 - i * 0.2) |
| 31 | group.add(plank) | 37 | group.add(plank) |
| 32 | } | 38 | } |
| 33 | | 39 | |
| 34 | - // Support posts | 40 | + // Support posts - two at shore, two at water end |
| 35 | - const postGeom = new THREE.CylinderGeometry(0.04, 0.05, 0.4, 6) | 41 | + const postGeom = new THREE.CylinderGeometry(0.05, 0.06, 0.5, 6) |
| 36 | const postPositions = [ | 42 | const postPositions = [ |
| 37 | - { x: -0.5, z: 0.25 }, | 43 | + // Shore posts (shorter, above ground) |
| 38 | - { x: -0.5, z: -0.25 }, | 44 | + { x: -dockWidth / 2 + 0.08, z: -0.1, height: 0.3, yOffset: -0.1 }, |
| 39 | - { x: 0.5, z: 0.25 }, | 45 | + { x: dockWidth / 2 - 0.08, z: -0.1, height: 0.3, yOffset: -0.1 }, |
| 40 | - { x: 0.5, z: -0.25 } | 46 | + // Water posts (longer, go into water) |
| | 47 | + { x: -dockWidth / 2 + 0.08, z: -dockLength + 0.15, height: 0.6, yOffset: -0.25 }, |
| | 48 | + { x: dockWidth / 2 - 0.08, z: -dockLength + 0.15, height: 0.6, yOffset: -0.25 } |
| 41 | ] | 49 | ] |
| 42 | | 50 | |
| 43 | for (const pos of postPositions) { | 51 | for (const pos of postPositions) { |
| 44 | - const post = new THREE.Mesh(postGeom, darkWoodMaterial) | 52 | + const pGeom = new THREE.CylinderGeometry(0.05, 0.06, pos.height, 6) |
| 45 | - post.position.set(pos.x, -0.15, pos.z) | 53 | + const post = new THREE.Mesh(pGeom, darkWoodMaterial) |
| | 54 | + post.position.set(pos.x, pos.yOffset, pos.z) |
| 46 | group.add(post) | 55 | group.add(post) |
| 47 | } | 56 | } |
| 48 | | 57 | |
| | 58 | + // Rope detail on water-end posts |
| | 59 | + const ropeMaterial = new THREE.MeshToonMaterial({ |
| | 60 | + color: 0x8b7355, |
| | 61 | + gradientMap |
| | 62 | + }) |
| | 63 | + const ropeGeom = new THREE.TorusGeometry(0.06, 0.015, 6, 12) |
| | 64 | + |
| | 65 | + // Rope on left water post |
| | 66 | + const ropeLeft = new THREE.Mesh(ropeGeom, ropeMaterial) |
| | 67 | + ropeLeft.position.set(-dockWidth / 2 + 0.08, 0.08, -dockLength + 0.15) |
| | 68 | + ropeLeft.rotation.x = Math.PI / 2 |
| | 69 | + group.add(ropeLeft) |
| | 70 | + |
| | 71 | + // Rope on right water post |
| | 72 | + const ropeRight = new THREE.Mesh(ropeGeom, ropeMaterial) |
| | 73 | + ropeRight.position.set(dockWidth / 2 - 0.08, 0.08, -dockLength + 0.15) |
| | 74 | + ropeRight.rotation.x = Math.PI / 2 |
| | 75 | + group.add(ropeRight) |
| | 76 | + |
| 49 | return group | 77 | return group |
| 50 | } | 78 | } |
| 51 | | 79 | |
| 52 | // Create a fishing hut | 80 | // Create a fishing hut |
| | 81 | +// Hut sits on shore with front porch extending toward water (-Z direction) |
| 53 | export function createFishingHut(gradientMap) { | 82 | export function createFishingHut(gradientMap) { |
| 54 | const group = new THREE.Group() | 83 | const group = new THREE.Group() |
| 55 | | 84 | |
@@ -69,36 +98,64 @@ export function createFishingHut(gradientMap) { |
| 69 | opacity: 0.6 | 98 | opacity: 0.6 |
| 70 | }) | 99 | }) |
| 71 | | 100 | |
| 72 | - // Base/floor | 101 | + const darkWoodMaterial = new THREE.MeshToonMaterial({ |
| 73 | - const baseGeom = new THREE.BoxGeometry(0.9, 0.06, 0.7) | 102 | + color: 0x5c4a1a, |
| | 103 | + gradientMap |
| | 104 | + }) |
| | 105 | + |
| | 106 | + // Front porch/deck extending into water |
| | 107 | + const porchGeom = new THREE.BoxGeometry(0.7, 0.06, 0.5) |
| | 108 | + const porch = new THREE.Mesh(porchGeom, darkWoodMaterial) |
| | 109 | + porch.position.set(0, 0.02, -0.25) |
| | 110 | + group.add(porch) |
| | 111 | + |
| | 112 | + // Porch support posts (in water) |
| | 113 | + const porchPostGeom = new THREE.CylinderGeometry(0.03, 0.04, 0.4, 6) |
| | 114 | + const porchPosts = [ |
| | 115 | + { x: -0.3, z: -0.45 }, |
| | 116 | + { x: 0.3, z: -0.45 } |
| | 117 | + ] |
| | 118 | + for (const pos of porchPosts) { |
| | 119 | + const post = new THREE.Mesh(porchPostGeom, darkWoodMaterial) |
| | 120 | + post.position.set(pos.x, -0.15, pos.z) |
| | 121 | + group.add(post) |
| | 122 | + } |
| | 123 | + |
| | 124 | + // Main building base/floor - offset onto shore |
| | 125 | + const baseGeom = new THREE.BoxGeometry(0.9, 0.08, 0.7) |
| 74 | const base = new THREE.Mesh(baseGeom, woodMaterial) | 126 | const base = new THREE.Mesh(baseGeom, woodMaterial) |
| 75 | - base.position.y = 0.03 | 127 | + base.position.set(0, 0.04, 0.35) |
| 76 | group.add(base) | 128 | group.add(base) |
| 77 | | 129 | |
| 78 | // Walls | 130 | // Walls |
| 79 | const wallGeom = new THREE.BoxGeometry(0.85, 0.5, 0.65) | 131 | const wallGeom = new THREE.BoxGeometry(0.85, 0.5, 0.65) |
| 80 | const walls = new THREE.Mesh(wallGeom, woodMaterial) | 132 | const walls = new THREE.Mesh(wallGeom, woodMaterial) |
| 81 | - walls.position.y = 0.31 | 133 | + walls.position.set(0, 0.33, 0.35) |
| 82 | group.add(walls) | 134 | group.add(walls) |
| 83 | | 135 | |
| 84 | // Roof | 136 | // Roof |
| 85 | const roofGeom = new THREE.ConeGeometry(0.55, 0.35, 4) | 137 | const roofGeom = new THREE.ConeGeometry(0.55, 0.35, 4) |
| 86 | const roof = new THREE.Mesh(roofGeom, roofMaterial) | 138 | const roof = new THREE.Mesh(roofGeom, roofMaterial) |
| 87 | - roof.position.y = 0.73 | 139 | + roof.position.set(0, 0.75, 0.35) |
| 88 | roof.rotation.y = Math.PI / 4 | 140 | roof.rotation.y = Math.PI / 4 |
| 89 | group.add(roof) | 141 | group.add(roof) |
| 90 | | 142 | |
| 91 | - // Window | 143 | + // Window (on side wall) |
| 92 | const windowGeom = new THREE.PlaneGeometry(0.15, 0.15) | 144 | const windowGeom = new THREE.PlaneGeometry(0.15, 0.15) |
| 93 | const window1 = new THREE.Mesh(windowGeom, windowMaterial) | 145 | const window1 = new THREE.Mesh(windowGeom, windowMaterial) |
| 94 | - window1.position.set(0.43, 0.35, 0) | 146 | + window1.position.set(0.43, 0.37, 0.35) |
| 95 | window1.rotation.y = Math.PI / 2 | 147 | window1.rotation.y = Math.PI / 2 |
| 96 | group.add(window1) | 148 | group.add(window1) |
| 97 | | 149 | |
| 98 | - // Door frame | 150 | + // Door (facing water) |
| 99 | - const doorGeom = new THREE.BoxGeometry(0.02, 0.35, 0.2) | 151 | + const doorFrameGeom = new THREE.BoxGeometry(0.22, 0.35, 0.03) |
| 100 | - const door = new THREE.Mesh(doorGeom, roofMaterial) | 152 | + const doorFrame = new THREE.Mesh(doorFrameGeom, roofMaterial) |
| 101 | - door.position.set(0.43, 0.24, 0) | 153 | + doorFrame.position.set(0, 0.26, 0.03) |
| | 154 | + group.add(doorFrame) |
| | 155 | + |
| | 156 | + const doorGeom = new THREE.BoxGeometry(0.18, 0.32, 0.02) |
| | 157 | + const door = new THREE.Mesh(doorGeom, darkWoodMaterial) |
| | 158 | + door.position.set(0, 0.24, 0.02) |
| 102 | group.add(door) | 159 | group.add(door) |
| 103 | | 160 | |
| 104 | return group | 161 | return group |