pillar jib animation bug fix
This commit is contained in:
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user