diff --git a/Week-2/Task-4/r3f/src/App.jsx b/Week-2/Task-4/r3f/src/App.jsx
index 625ff5b..54e8e94 100644
--- a/Week-2/Task-4/r3f/src/App.jsx
+++ b/Week-2/Task-4/r3f/src/App.jsx
@@ -1,6 +1,172 @@
-export default function App() {
+import { useEffect, useMemo, useRef, useState } from 'react'
+import { Canvas, useFrame, useThree } from '@react-three/fiber'
+import * as THREE from 'three'
+
+const STEPS = [
+ {
+ label: 'Step 1: Group at rest',
+ detail: 'Parent group is centered and children keep their offsets.',
+ cameraPosition: [0, 1.7, 6],
+ lookAt: [0, 0, 0],
+ groupPosition: [0, 0, 0],
+ groupRotation: [0, 0, 0],
+ spinSpeed: 0,
+ },
+ {
+ label: 'Step 2: Parent rotation',
+ detail: 'Only parent rotates; children move together without changing local layout.',
+ cameraPosition: [1.7, 1.8, 5.6],
+ lookAt: [0, 0, 0],
+ groupPosition: [0, 0, 0],
+ groupRotation: [0.15, 0.55, 0],
+ spinSpeed: 0.015,
+ },
+ {
+ label: 'Step 3: Parent move + rotate',
+ detail: 'Parent shifts and rotates as one unit while child spacing stays intact.',
+ cameraPosition: [0.6, 2.4, 7],
+ lookAt: [0.4, 0.35, 0],
+ groupPosition: [0.7, 0.4, -0.4],
+ groupRotation: [0.35, 1.2, 0.2],
+ spinSpeed: 0.03,
+ },
+]
+
+function GuidedGroupScene({ stepIndex }) {
+ const { camera } = useThree()
+ const groupRef = useRef()
+
+ const targets = useMemo(
+ () => ({
+ cameraPosition: new THREE.Vector3(),
+ cameraLookAt: new THREE.Vector3(),
+ lookCurrent: new THREE.Vector3(),
+ groupPosition: new THREE.Vector3(),
+ groupRotation: new THREE.Euler(),
+ spinSpeed: 0,
+ initialized: false,
+ }),
+ []
+ )
+
+ useEffect(() => {
+ const step = STEPS[stepIndex]
+
+ targets.cameraPosition.set(...step.cameraPosition)
+ targets.cameraLookAt.set(...step.lookAt)
+ targets.groupPosition.set(...step.groupPosition)
+ targets.groupRotation.set(...step.groupRotation)
+ targets.spinSpeed = step.spinSpeed
+
+ if (groupRef.current && !targets.initialized) {
+ camera.position.copy(targets.cameraPosition)
+ targets.lookCurrent.copy(targets.cameraLookAt)
+ groupRef.current.position.copy(targets.groupPosition)
+ groupRef.current.rotation.copy(targets.groupRotation)
+ targets.initialized = true
+ }
+ }, [camera, stepIndex, targets])
+
+ useFrame(() => {
+ if (!groupRef.current) return
+
+ groupRef.current.position.lerp(targets.groupPosition, 0.1)
+
+ groupRef.current.rotation.x += (targets.groupRotation.x - groupRef.current.rotation.x) * 0.1
+ groupRef.current.rotation.y += (targets.groupRotation.y - groupRef.current.rotation.y) * 0.1
+ groupRef.current.rotation.z += (targets.groupRotation.z - groupRef.current.rotation.z) * 0.1
+
+ groupRef.current.rotation.y += targets.spinSpeed * 0.2
+
+ camera.position.lerp(targets.cameraPosition, 0.08)
+ targets.lookCurrent.lerp(targets.cameraLookAt, 0.08)
+ camera.lookAt(targets.lookCurrent)
+ })
+
return (
- <>>
+ <>
+
{step.label}
+{step.detail}
+ +Simple parent group animation. Keys: 1, 2, 3.
+