pillar jib animation bug fix

This commit is contained in:
2025-09-02 18:00:12 +05:30
parent 25e4628f75
commit 58007a96dc

View File

@@ -167,7 +167,7 @@ function PillarJibAnimator({
const trolley = model.getObjectByName('trolley');
const hook = model.getObjectByName('hook');
if (!base || !trolley || !hook || !trolley.parent) return;
if (!base || !trolley || !hook || !trolley.parent || !hook.parent) return;
const baseWorld = new THREE.Vector3();
base.getWorldPosition(baseWorld);
@@ -175,18 +175,6 @@ function PillarJibAnimator({
const hookWorld = new THREE.Vector3();
hook.getWorldPosition(hookWorld);
if (!model.userData.animationData) {
model.userData.animationData = {
originalHookY: hook.position.y,
targetHookY: clampedPoints[0].y - baseWorld.y,
targetDirection: new THREE.Vector2(),
targetTrolleyX: 0,
targetWorldPosition: clampedPoints[0].clone(),
finalHookTargetY: 0,
};
}
const { animationData } = model.userData;
const hookSpeed = (model.userData.hookSpeed || 0.01) * speed;
const rotationSpeed = (model.userData.rotationSpeed || 0.005) * speed;
const trolleySpeed = (model.userData.trolleySpeed || 0.01) * speed;
@@ -197,28 +185,37 @@ function PillarJibAnimator({
case 'init-hook-adjust': {
const hookWorld = new THREE.Vector3();
hook.getWorldPosition(hookWorld);
const targetY = clampedPoints[0].y;
const direction = Math.sign(targetY - hookWorld.y);
const diff = targetY - hookWorld.y;
hook.position.y = THREE.MathUtils.lerp(
hook.position.y,
hook.position.y + direction * 0.1,
Math.min(hookSpeed, 0.9)
);
if (Math.abs(hookWorld.y - targetY) < threshold) {
hook.position.y = targetY - baseWorld.y;
if (Math.abs(diff) > threshold) {
const step = Math.sign(diff) * hookSpeed;
if (Math.abs(step) > Math.abs(diff)) {
const localTarget = hook.parent.worldToLocal(clampedPoints[0].clone());
hook.position.y = localTarget.y;
setAnimationPhase('init-rotate-base');
} else {
hook.position.y += step;
}
} else {
const localTarget = hook.parent.worldToLocal(clampedPoints[0].clone());
hook.position.y = localTarget.y;
setAnimationPhase('init-rotate-base');
}
break;
}
case 'init-rotate-base': {
const baseWorld = new THREE.Vector3();
base.getWorldPosition(baseWorld);
const baseForward = new THREE.Vector3(1, 0, 0);
base.localToWorld(baseForward);
baseForward.sub(baseWorld);
const currentDir = new THREE.Vector2(baseForward.x, baseForward.z).normalize();
const targetWorld = clampedPoints[0];
const targetDir = new THREE.Vector2(
targetWorld.x - baseWorld.x,
@@ -228,79 +225,102 @@ function PillarJibAnimator({
const currentAngle = Math.atan2(currentDir.y, currentDir.x);
const targetAngle = Math.atan2(targetDir.y, targetDir.x);
let angleDiff = currentAngle - targetAngle;
angleDiff = Math.atan2(Math.sin(angleDiff), Math.cos(angleDiff));
if (Math.abs(angleDiff) > threshold) {
base.rotation.y = THREE.MathUtils.lerp(
base.rotation.y,
base.rotation.y - angleDiff,
Math.min(rotationSpeed, 0.9)
);
if (parseFloat(Math.abs(angleDiff).toFixed(2)) > 0.05) {
const step = Math.sign(angleDiff) * rotationSpeed;
if (Math.abs(step) > Math.abs(angleDiff)) {
base.rotation.y += angleDiff;
setAnimationPhase('init-move-trolley');
} else {
base.rotation.y += step;
}
} else {
base.rotation.y -= angleDiff;
const localTarget = trolley.parent.worldToLocal(clampedPoints[0].clone());
animationData.targetTrolleyX = localTarget?.x;
base.rotation.y += angleDiff;
setAnimationPhase('init-move-trolley');
}
break;
}
case 'init-move-trolley': {
const dx = animationData.targetTrolleyX - trolley.position.x;
const baseWorld = new THREE.Vector3();
base.getWorldPosition(baseWorld);
trolley.position.x = THREE.MathUtils.lerp(
trolley.position.x,
animationData.targetTrolleyX,
Math.min(trolleySpeed, 0.9)
);
const targetWorld = clampedPoints[0].clone();
const localTarget = trolley.parent.worldToLocal(targetWorld.clone());
if (Math.abs(dx) < threshold) {
trolley.position.x = animationData.targetTrolleyX;
animationData.finalHookTargetY = clampedPoints[0].y - baseWorld.y;
const diff = localTarget.x - trolley.position.x;
if (Math.abs(diff) > threshold) {
const step = Math.sign(diff) * trolleySpeed;
if (Math.abs(step) > Math.abs(diff)) {
trolley.position.x = localTarget.x;
setAnimationPhase('init-final-hook-adjust');
} else {
trolley.position.x += step;
}
} else {
trolley.position.x = localTarget.x;
setAnimationPhase('init-final-hook-adjust');
}
break;
}
case 'init-final-hook-adjust': {
const targetY = clampedPoints[0].y - baseWorld.y;
const hookWorld = new THREE.Vector3();
hook.getWorldPosition(hookWorld);
hook.position.y = THREE.MathUtils.lerp(
hook.position.y,
targetY,
Math.min(hookSpeed, 0.9)
);
const targetY = clampedPoints[0].y;
const diff = targetY - hookWorld.y;
if (Math.abs(hook.position.y - targetY) < threshold) {
hook.position.y = targetY;
model.userData.animationData = {
originalHookY: hook.position.y,
targetHookY: clampedPoints[1].y - baseWorld.y + 0.5,
targetDirection: new THREE.Vector2(),
targetTrolleyX: 0,
targetWorldPosition: clampedPoints[1].clone(),
finalHookTargetY: 0,
};
setAnimationPhase('starting');
onAnimationComplete('starting');
if (Math.abs(diff) > threshold) {
const step = Math.sign(diff) * hookSpeed;
if (Math.abs(step) > Math.abs(diff)) {
const localTarget = hook.parent.worldToLocal(clampedPoints[0].clone());
hook.position.y = localTarget.y;
setAnimationPhase('first-hook-adjust');
} else {
hook.position.y += step;
}
} else {
const localTarget = hook.parent.worldToLocal(clampedPoints[0].clone());
hook.position.y = localTarget.y;
setAnimationPhase('first-hook-adjust');
}
break;
}
case 'first-hook-adjust': {
const direction = Math.sign(animationData.targetHookY - hook.position.y);
hook.position.y += direction * hookSpeed;
const hookWorld = new THREE.Vector3();
hook.getWorldPosition(hookWorld);
if (parseFloat(Math.abs(hook.position.y - animationData.targetHookY).toFixed(2)) < 0.05) {
hook.position.y = animationData.targetHookY;
const targetWorld = clampedPoints[1].clone().add(new THREE.Vector3(0, 0.5, 0));
const targetY = targetWorld.y;
const diff = targetY - hookWorld.y;
if (Math.abs(diff) > threshold) {
const step = Math.sign(diff) * hookSpeed;
if (Math.abs(step) > Math.abs(diff)) {
const localTarget = hook.parent.worldToLocal(targetWorld.clone());
hook.position.y = localTarget.y;
setAnimationPhase('first-rotate-base');
} else {
hook.position.y += step;
}
} else {
const localTarget = hook.parent.worldToLocal(targetWorld.clone());
hook.position.y = localTarget.y;
setAnimationPhase('first-rotate-base');
}
break;
}
case 'first-rotate-base': {
const baseWorld = new THREE.Vector3();
base.getWorldPosition(baseWorld);
const baseForward = new THREE.Vector3(1, 0, 0);
base.localToWorld(baseForward);
baseForward.sub(baseWorld);
@@ -320,37 +340,70 @@ function PillarJibAnimator({
angleDiff = Math.atan2(Math.sin(angleDiff), Math.cos(angleDiff));
if (parseFloat(Math.abs(angleDiff).toFixed(2)) > 0.05) {
base.rotation.y += Math.sign(angleDiff) * rotationSpeed;
const step = Math.sign(angleDiff) * rotationSpeed;
if (Math.abs(step) > Math.abs(angleDiff)) {
base.rotation.y += angleDiff;
setAnimationPhase('first-move-trolley');
} else {
base.rotation.y += step;
}
} else {
base.rotation.y += angleDiff;
const localTarget = trolley.parent.worldToLocal(clampedPoints[1].clone());
animationData.targetTrolleyX = localTarget?.x;
setAnimationPhase('first-move-trolley');
}
break;
}
case 'first-move-trolley': {
const dx = animationData.targetTrolleyX - trolley.position.x;
const direction = Math.sign(dx);
trolley.position.x += direction * trolleySpeed;
const baseWorld = new THREE.Vector3();
base.getWorldPosition(baseWorld);
if (parseFloat(Math.abs(dx).toFixed(2)) < 0.05) {
trolley.position.x = animationData.targetTrolleyX;
const targetWorld = clampedPoints[1].clone();
const localTarget = trolley.parent.worldToLocal(targetWorld.clone());
animationData.finalHookTargetY = hook.position.y - 0.5;
const diff = localTarget.x - trolley.position.x;
if (Math.abs(diff) > threshold) {
const step = Math.sign(diff) * trolleySpeed;
if (Math.abs(step) > Math.abs(diff)) {
trolley.position.x = localTarget.x;
setAnimationPhase('first-final-hook-adjust');
} else {
trolley.position.x += step;
}
} else {
trolley.position.x = localTarget.x;
setAnimationPhase('first-final-hook-adjust');
}
break;
}
case 'first-final-hook-adjust': {
const dy = animationData.finalHookTargetY - hook.position.y;
const direction = Math.sign(dy);
hook.position.y += direction * hookSpeed;
const hookWorld = new THREE.Vector3();
hook.getWorldPosition(hookWorld);
if (parseFloat(Math.abs(dy).toFixed(2)) < 0.05) {
hook.position.y = animationData.finalHookTargetY;
const targetY = clampedPoints[1].y;
const diff = targetY - hookWorld.y;
if (Math.abs(diff) > threshold) {
const step = Math.sign(diff) * hookSpeed;
if (Math.abs(step) > Math.abs(diff)) {
const localTarget = hook.parent.worldToLocal(clampedPoints[1].clone());
hook.position.y = localTarget.y;
if (crane.currentPhase === 'init-pickup') {
setAnimationPhase('picking');
onAnimationComplete('picking');
} else if (crane.currentPhase === 'pickup-drop') {
setAnimationPhase('dropping');
onAnimationComplete('dropping');
}
} else {
hook.position.y += step;
}
} else {
const localTarget = hook.parent.worldToLocal(clampedPoints[1].clone());
hook.position.y = localTarget.y;
if (crane.currentPhase === 'init-pickup') {
setAnimationPhase('picking');
onAnimationComplete('picking');