@@ -200,12 +200,13 @@ export function createDonny(scene, gradientMap) { |
| 200 | state.timer += delta | 200 | state.timer += delta |
| 201 | | 201 | |
| 202 | // Calculate angle to face Doug | 202 | // Calculate angle to face Doug |
| | 203 | + // Model faces +X, so we offset by -PI/2 |
| 203 | let angleToDoug = 0 | 204 | let angleToDoug = 0 |
| 204 | if (doug) { | 205 | if (doug) { |
| 205 | const dougPos = doug.getPosition() | 206 | const dougPos = doug.getPosition() |
| 206 | const dx = dougPos.x - group.position.x | 207 | const dx = dougPos.x - group.position.x |
| 207 | const dz = dougPos.z - group.position.z | 208 | const dz = dougPos.z - group.position.z |
| 208 | - angleToDoug = Math.atan2(dx, dz) | 209 | + angleToDoug = Math.atan2(dx, dz) - Math.PI / 2 |
| 209 | } | 210 | } |
| 210 | | 211 | |
| 211 | switch (state.mode) { | 212 | switch (state.mode) { |
@@ -237,16 +238,16 @@ export function createDonny(scene, gradientMap) { |
| 237 | // Rise from the water | 238 | // Rise from the water |
| 238 | const emergeProgress = Math.min(state.timer / 1.5, 1) | 239 | const emergeProgress = Math.min(state.timer / 1.5, 1) |
| 239 | const easeOut = 1 - Math.pow(1 - emergeProgress, 3) | 240 | const easeOut = 1 - Math.pow(1 - emergeProgress, 3) |
| 240 | - group.position.y = -2 + easeOut * 2.3 // Rise to 0.3 above water | 241 | + group.position.y = -2 + easeOut * 1.8 // Rise so rear stays submerged |
| 241 | | 242 | |
| 242 | - // Tilt upward as emerging (nose up!) | 243 | + // Tilt nose UP, rear submerged (positive X rotation) |
| 243 | - group.rotation.x = -0.3 * easeOut | 244 | + group.rotation.x = 0.45 * easeOut |
| 244 | | 245 | |
| 245 | // Slowly turn toward Doug - lugubrious, not laser tracking | 246 | // Slowly turn toward Doug - lugubrious, not laser tracking |
| 246 | - group.rotation.y = lerpAngle(group.rotation.y, angleToDoug, delta * 0.3) | 247 | + group.rotation.y = lerpAngle(group.rotation.y, angleToDoug, delta * 0.5) |
| 247 | | 248 | |
| 248 | // Gentle rocking as emerging | 249 | // Gentle rocking as emerging |
| 249 | - group.rotation.z = Math.sin(state.timer * 4) * 0.1 | 250 | + group.rotation.z = Math.sin(state.timer * 4) * 0.08 |
| 250 | | 251 | |
| 251 | if (emergeProgress >= 1) { | 252 | if (emergeProgress >= 1) { |
| 252 | state.mode = 'surfaced' | 253 | state.mode = 'surfaced' |
@@ -256,13 +257,13 @@ export function createDonny(scene, gradientMap) { |
| 256 | break | 257 | break |
| 257 | | 258 | |
| 258 | case 'surfaced': | 259 | case 'surfaced': |
| 259 | - // Bob gently on the surface | 260 | + // Bob gently, rear stays in water |
| 260 | - group.position.y = 0.3 + Math.sin(elapsed * 2) * 0.08 | 261 | + group.position.y = -0.2 + Math.sin(elapsed * 2) * 0.06 |
| 261 | - group.rotation.z = Math.sin(elapsed * 1.5) * 0.05 | 262 | + group.rotation.z = Math.sin(elapsed * 1.5) * 0.04 |
| 262 | | 263 | |
| 263 | - // Keep tilted upward, slowly drifting gaze toward Doug | 264 | + // Keep tilted - nose up, tail submerged |
| 264 | - group.rotation.x = -0.25 + Math.sin(elapsed * 1.5) * 0.05 | 265 | + group.rotation.x = 0.4 + Math.sin(elapsed * 1.5) * 0.05 |
| 265 | - group.rotation.y = lerpAngle(group.rotation.y, angleToDoug, delta * 0.2) | 266 | + group.rotation.y = lerpAngle(group.rotation.y, angleToDoug, delta * 0.3) |
| 266 | | 267 | |
| 267 | // Gentle flipper animation | 268 | // Gentle flipper animation |
| 268 | leftFlipper.rotation.z = 2.2 + Math.sin(elapsed * 3) * 0.15 | 269 | leftFlipper.rotation.z = 2.2 + Math.sin(elapsed * 3) * 0.15 |
@@ -286,10 +287,10 @@ export function createDonny(scene, gradientMap) { |
| 286 | // Sink back down | 287 | // Sink back down |
| 287 | const submergeProgress = Math.min(state.timer / 1.2, 1) | 288 | const submergeProgress = Math.min(state.timer / 1.2, 1) |
| 288 | const easeIn = Math.pow(submergeProgress, 2) | 289 | const easeIn = Math.pow(submergeProgress, 2) |
| 289 | - group.position.y = 0.3 - easeIn * 2.5 | 290 | + group.position.y = -0.2 - easeIn * 2 |
| 290 | | 291 | |
| 291 | - // Tilt nose down as submerging | 292 | + // Tilt nose down as diving back under |
| 292 | - group.rotation.x = -0.25 + easeIn * 0.4 | 293 | + group.rotation.x = 0.4 - easeIn * 0.6 |
| 293 | | 294 | |
| 294 | // Add bubbles/ripples as submerging | 295 | // Add bubbles/ripples as submerging |
| 295 | if (Math.random() < delta * 4) { | 296 | if (Math.random() < delta * 4) { |