diff --git a/Week-1/Task-3/r3f/index.html b/Week-1/Task-3/r3f/index.html
new file mode 100644
index 0000000..22e4ebb
--- /dev/null
+++ b/Week-1/Task-3/r3f/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+ Task 3 R3F - Cube Clone
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week-1/Task-3/r3f/package.json b/Week-1/Task-3/r3f/package.json
index 97b288b..5056248 100644
--- a/Week-1/Task-3/r3f/package.json
+++ b/Week-1/Task-3/r3f/package.json
@@ -2,11 +2,23 @@
"name": "week-1-task-3-r3f",
"private": true,
"version": "0.0.0",
+ "type": "module",
"packageManager": "yarn@1.22.22",
"scripts": {
- "dev": "echo 'Add your React Three Fiber dev script here'",
- "build": "echo 'Add your React Three Fiber build script here'",
- "lint": "echo 'Add your lint script here'",
+ "dev": "vite",
+ "build": "vite build",
+ "lint": "echo 'Lint not configured yet'",
+ "preview": "vite preview",
"clean": "rm -rf dist build .next"
+ },
+ "dependencies": {
+ "@react-three/fiber": "^9.5.0",
+ "react": "^19.2.4",
+ "react-dom": "^19.2.4",
+ "three": "^0.183.2"
+ },
+ "devDependencies": {
+ "@vitejs/plugin-react": "^6.0.0",
+ "vite": "^8.0.3"
}
}
\ No newline at end of file
diff --git a/Week-1/Task-3/r3f/src/App.jsx b/Week-1/Task-3/r3f/src/App.jsx
new file mode 100644
index 0000000..44f01cc
--- /dev/null
+++ b/Week-1/Task-3/r3f/src/App.jsx
@@ -0,0 +1,16 @@
+import { Canvas } from '@react-three/fiber'
+import CubePair from './CubeDuplicate'
+import GroupedStructure from './Group'
+
+export default function App() {
+ return (
+
+ )
+}
diff --git a/Week-1/Task-3/r3f/src/CubeDuplicate.jsx b/Week-1/Task-3/r3f/src/CubeDuplicate.jsx
new file mode 100644
index 0000000..53bd2b8
--- /dev/null
+++ b/Week-1/Task-3/r3f/src/CubeDuplicate.jsx
@@ -0,0 +1,47 @@
+import { useFrame } from '@react-three/fiber'
+import { useEffect, useMemo, useRef } from 'react'
+import * as THREE from 'three'
+
+function CubePair() {
+ const leftCubeRef = useRef()
+ const rightCubeRef = useRef()
+
+ const sharedGeometry = useMemo(() => new THREE.BoxGeometry(1, 1, 1), [])
+ const sharedMaterial = useMemo(() => new THREE.MeshStandardMaterial({ color: '#5bc0eb' }), [])
+
+ useEffect(() => {
+ return () => {
+ sharedGeometry.dispose()
+ sharedMaterial.dispose()
+ }
+ }, [sharedGeometry, sharedMaterial])
+
+ useFrame((state) => {
+ const seconds = state.clock.elapsedTime
+
+ if (leftCubeRef.current) {
+ leftCubeRef.current.rotation.x = seconds
+ leftCubeRef.current.rotation.y = seconds
+ }
+
+ if (rightCubeRef.current) {
+ rightCubeRef.current.rotation.x = seconds
+ rightCubeRef.current.rotation.y = -seconds
+ }
+ })
+
+ return (
+ <>
+
+
+
+ >
+ )
+}
+
+export default CubePair
\ No newline at end of file
diff --git a/Week-1/Task-3/r3f/src/Group.jsx b/Week-1/Task-3/r3f/src/Group.jsx
new file mode 100644
index 0000000..4f87dea
--- /dev/null
+++ b/Week-1/Task-3/r3f/src/Group.jsx
@@ -0,0 +1,44 @@
+import { Canvas, useFrame } from '@react-three/fiber'
+import { useRef } from 'react'
+
+function GroupedStructure({ position = [0, 0, 0], direction = 1 }) {
+ const groupRef = useRef()
+
+ useFrame((state) => {
+ const seconds = state.clock.elapsedTime
+
+ if (!groupRef.current) return
+
+ groupRef.current.rotation.y = direction * seconds * 0.7
+ groupRef.current.rotation.x = Math.sin(seconds * 1.1) * 0.2
+ })
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default GroupedStructure
+
+// export default function GroupApp() {
+// return (
+//
+// )
+// }
diff --git a/Week-1/Task-3/r3f/src/index.css b/Week-1/Task-3/r3f/src/index.css
new file mode 100644
index 0000000..77c24e1
--- /dev/null
+++ b/Week-1/Task-3/r3f/src/index.css
@@ -0,0 +1,18 @@
+html,
+body,
+#root {
+ margin: 0;
+ width: 100%;
+ height: 100%;
+}
+
+body {
+ overflow: hidden;
+ background: #101418;
+}
+
+canvas {
+ display: block;
+ width: 100%;
+ height: 100%;
+}
\ No newline at end of file
diff --git a/Week-1/Task-3/r3f/src/main.jsx b/Week-1/Task-3/r3f/src/main.jsx
new file mode 100644
index 0000000..104325b
--- /dev/null
+++ b/Week-1/Task-3/r3f/src/main.jsx
@@ -0,0 +1,10 @@
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+import App from './App.jsx'
+import './index.css'
+
+createRoot(document.getElementById('root')).render(
+
+
+ ,
+)
diff --git a/Week-1/Task-3/r3f/vite.config.js b/Week-1/Task-3/r3f/vite.config.js
new file mode 100644
index 0000000..9ffcc67
--- /dev/null
+++ b/Week-1/Task-3/r3f/vite.config.js
@@ -0,0 +1,6 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+export default defineConfig({
+ plugins: [react()],
+})
diff --git a/Week-1/Task-3/vanilla/group.js b/Week-1/Task-3/vanilla/group.js
new file mode 100644
index 0000000..530d93c
--- /dev/null
+++ b/Week-1/Task-3/vanilla/group.js
@@ -0,0 +1,68 @@
+import * as THREE from "three"
+
+const renderer = new THREE.WebGLRenderer({ antialias: true })
+renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
+document.body.appendChild(renderer.domElement)
+
+const scene = new THREE.Scene()
+scene.background = new THREE.Color(0x101418)
+
+const camera = new THREE.PerspectiveCamera(60, 2, 0.1, 100)
+camera.position.set(0, 1.2, 8)
+
+scene.add(new THREE.AmbientLight(0xffffff, 0.65))
+
+const light = new THREE.DirectionalLight(0xffffff, 1.1)
+light.position.set(4, 6, 5)
+scene.add(light)
+
+const pillarGeometry = new THREE.BoxGeometry(0.7, 1.6, 0.7)
+const pillarMaterial = new THREE.MeshStandardMaterial({ color: 0xf6bd60 })
+const capGeometry = new THREE.SphereGeometry(0.4, 24, 24)
+const capMaterial = new THREE.MeshStandardMaterial({ color: 0x84a59d })
+
+const groupedStructure = new THREE.Group()
+
+const pillar = new THREE.Mesh(pillarGeometry, pillarMaterial)
+pillar.position.y = -0.2
+groupedStructure.add(pillar)
+
+const cap = new THREE.Mesh(capGeometry, capMaterial)
+cap.position.y = 0.95
+groupedStructure.add(cap)
+
+groupedStructure.position.set(-1.4, 0, 0)
+scene.add(groupedStructure)
+
+const groupedStructureClone = groupedStructure.clone()
+groupedStructureClone.position.set(1.4, 0, 0)
+scene.add(groupedStructureClone)
+
+function resizeRendererToDisplaySize() {
+ const width = window.innerWidth
+ const height = window.innerHeight
+ const needResize = renderer.domElement.width !== width || renderer.domElement.height !== height
+
+ if (needResize) {
+ renderer.setSize(width, height, false)
+ camera.aspect = width / height
+ camera.updateProjectionMatrix()
+ }
+}
+
+function animate(time) {
+ const seconds = time * 0.001
+
+ resizeRendererToDisplaySize()
+
+ groupedStructure.rotation.y = seconds * 0.7
+ groupedStructure.rotation.x = Math.sin(seconds * 1.1) * 0.2
+
+ groupedStructureClone.rotation.y = -seconds * 0.7
+ groupedStructureClone.rotation.x = Math.sin(seconds * 1.1) * 0.2
+
+ renderer.render(scene, camera)
+ requestAnimationFrame(animate)
+}
+
+requestAnimationFrame(animate)
diff --git a/Week-1/Task-3/vanilla/index.html b/Week-1/Task-3/vanilla/index.html
new file mode 100644
index 0000000..9e23b4f
--- /dev/null
+++ b/Week-1/Task-3/vanilla/index.html
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+ Task 3 Vanilla - Duplication Tests
+
+
+
+
+
+
+
+
diff --git a/Week-1/Task-3/vanilla/main.js b/Week-1/Task-3/vanilla/main.js
new file mode 100644
index 0000000..f97407a
--- /dev/null
+++ b/Week-1/Task-3/vanilla/main.js
@@ -0,0 +1,56 @@
+import * as THREE from "three"
+const renderer = new THREE.WebGLRenderer({ antialias: true });
+renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
+document.body.appendChild(renderer.domElement);
+
+const scene = new THREE.Scene();
+scene.background = new THREE.Color(0x101418);
+
+const camera = new THREE.PerspectiveCamera(60, 2, 0.1, 100);
+camera.position.set(0, 0, 6);
+
+scene.add(new THREE.AmbientLight(0xffffff, 0.6));
+
+const light = new THREE.DirectionalLight(0xffffff, 1.1);
+light.position.set(4, 6, 5);
+scene.add(light);
+
+const geometry = new THREE.BoxGeometry(1, 1, 1);
+const material = new THREE.MeshStandardMaterial({ color: 0x5bc0eb });
+
+const cube = new THREE.Mesh(geometry, material);
+cube.position.x = -1.2;
+scene.add(cube);
+
+const cubeClone = cube.clone();
+cubeClone.position.x = 1.2;
+scene.add(cubeClone);
+
+function resizeRendererToDisplaySize() {
+ const width = window.innerWidth;
+ const height = window.innerHeight;
+ const needResize = renderer.domElement.width !== width || renderer.domElement.height !== height;
+
+ if (needResize) {
+ renderer.setSize(width, height, false);
+ camera.aspect = width / height;
+ camera.updateProjectionMatrix();
+ }
+}
+
+function animate(time) {
+ const seconds = time * 0.001;
+
+ resizeRendererToDisplaySize();
+
+ cube.rotation.x = seconds;
+ cube.rotation.y = seconds;
+
+ cubeClone.rotation.x = seconds;
+ cubeClone.rotation.y = -seconds;
+
+ renderer.render(scene, camera);
+ requestAnimationFrame(animate);
+}
+
+requestAnimationFrame(animate);
diff --git a/Week-1/Task-3/vanilla/package.json b/Week-1/Task-3/vanilla/package.json
index 324f5fa..1c1fe33 100644
--- a/Week-1/Task-3/vanilla/package.json
+++ b/Week-1/Task-3/vanilla/package.json
@@ -4,8 +4,10 @@
"version": "0.0.0",
"packageManager": "yarn@1.22.22",
"scripts": {
- "dev": "echo 'Add your Three.js dev script here'",
- "build": "echo 'Add your Three.js build script here'",
+ "dev": "vite",
+ "dev:object": "vite --open '/'",
+ "dev:group": "vite --open '/?test=group'",
+ "build": "vite build",
"lint": "echo 'Add your lint script here'",
"clean": "rm -rf dist build"
}