Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Submission for Team Aether #27

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.App {
text-align: center;
}

.App-logo {
height: 40vmin;
pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}

.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}

.App-link {
color: #61dafb;
}

@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
286 changes: 286 additions & 0 deletions App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
import React, { useRef, useState, useEffect } from 'react';
import { Canvas, useFrame, useLoader } from '@react-three/fiber';
import { OrbitControls, Stars, Html } from '@react-three/drei';
import * as THREE from 'three';
import { TextureLoader } from 'three';
import { EffectComposer, Bloom, DepthOfField } from '@react-three/postprocessing';

import starrygoodbye from './assets/starrygoodbye.mp3';
import soundoff from './assets/soundoff.png';
import soundon from './assets/soundon.png';


const AU = 15; // Distance of Earth from the Sun (in some assumed units)
// Sun Component
function Sun() {
const audioRef = useRef(new Audio(starrygoodbye));
audioRef.current.volume = 0.4;
audioRef.current.loop = true;
const [isPlayingMusic, setIsPlayingMusic] = useState(false);

useEffect(() => {
if(isPlayingMusic) {
audioRef.current.play();
}

return () => {
audioRef.current.pause();
}
}, [isPlayingMusic])


const sunRef = useRef();
const [scale, setScale] = useState(0.95);
const [direction, setDirection] = useState(1); // 1 for increasing, -1 for decreasing
// Loading the Sun texture
const textureUrl = `${process.env.PUBLIC_URL}/textures/sun.jpg`;
const sunTexture = useLoader(THREE.TextureLoader, textureUrl);
useFrame(() => {
setScale((prev) => {
// Update scale based on current direction
const newScale = prev + 0.00 * direction;

// Check if we need to switch direction
if (newScale >= 1) {
setDirection(-1); // Switch to decreasing
return 1; // Cap at 1
} else if (newScale <= 0.9) {
setDirection(1); // Switch to increasing
return 0.9; // Cap at 0.9
}

return newScale; // Return the new scale
});

// Setting the scale of the Sun
sunRef.current.scale.set(scale, scale, scale);
});


return (
<>
<mesh ref={sunRef}>
<sphereGeometry args={[4, 32, 32]} />
<meshStandardMaterial map={sunTexture} />
</mesh>
<mesh>
<sphereGeometry args={[1,6, 32, 32]} />
<meshBasicMaterial color="orange" />
</mesh>
</>
);
}


// Earth Component with Texture
function Earth() {
const earthRef = useRef();
const [angle, setAngle] = useState(0);
const [earthLabelPosition, setEarthLabelPosition] = useState([0, 0, 0]); // Store label position

const textureUrl = `${process.env.PUBLIC_URL}/textures/Earth1.jpg`;
const earthTexture = useLoader(THREE.TextureLoader, textureUrl);

useFrame(() => {
setAngle((prev) => prev + 0.01);
if (earthRef.current) { // Ensure earthRef.current is defined
const xPos = AU * Math.cos(angle);
const zPos = AU * Math.sin(angle);
earthRef.current.position.set(xPos, 0, zPos);

// Update the label position based on earth's position
setEarthLabelPosition([xPos, -2, zPos]); // Adjust label's Y position if needed
}
});

return (
<>
<mesh ref={earthRef}>
<sphereGeometry args={[2, 32, 32]} />
<meshStandardMaterial map={earthTexture} />
</mesh>
<mesh rotation={[Math.PI / 2, 0, 0]}>
<torusGeometry args={[AU, 0.1, 16, 100]} />
<meshBasicMaterial color="lightblue" transparent opacity={0.4} />
</mesh>

{/* Earth Label */}
<Html position={earthLabelPosition}>
<div style={{ color: 'rgb(115, 206, 235)' }}>Earth</div>
</Html>
</>
);
}

//Nebula Background
function NebulaBackground() {
const texture = useLoader(TextureLoader, process.env.PUBLIC_URL + "/textures/Nebula.png");

return (
<mesh position={[0, 0, -70]}> {/* Position the nebula in the background */}
<planeGeometry args={[300, 300]} /> {/* Large plane for the nebula */}
<meshBasicMaterial map={texture} side={2} /> {/* Ensure the nebula is visible from both sides */}
</mesh>
);
}

// L2Point Component
function L2Point() {
const l2Ref = useRef();
const [l2Angle, setL2Angle] = useState(0);
const L2_RADIUS = AU + 6;

const textureUrl = `${process.env.PUBLIC_URL}/textures/RedL2.png`;
const l2Texture = useLoader(THREE.TextureLoader, textureUrl);

useFrame(() => {
setL2Angle((prev) => prev + 0.01);
l2Ref.current.position.x = L2_RADIUS * Math.cos(l2Angle);
l2Ref.current.position.z = L2_RADIUS * Math.sin(l2Angle);
l2Ref.current.position.y = 0;
});

return (
<>
<mesh ref={l2Ref}>
<sphereGeometry args={[0.5, 32, 32]} />
<meshStandardMaterial map={l2Texture} transparent opacity={0.99} />
</mesh>
<mesh rotation={[Math.PI / 2, 0, 0]}>
<torusGeometry args={[L2_RADIUS, 0.05, 16, 100]} />
<meshBasicMaterial color="purple" transparent opacity={0.5} />
</mesh>

{/* L2 Point Label */}
<Html position={[L2_RADIUS * Math.cos(l2Angle), -2, L2_RADIUS * Math.sin(l2Angle)]}>
<div style={{ color: 'rgb(225, 40, 40)' }}>L2 Point</div>
</Html>
</>
);
}





// JWST Component
function JWST() {
const jwstRef = useRef();
const [angle, setAngle] = useState(0);
const L2_RADIUS = AU + 5;
const JWST_DISTANCE = 3;

const [l2Angle, setL2Angle] = useState(0);
const [jwstPosition, setJwstPosition] = useState({ x: 0, y: 0, z: 0 });

useFrame(() => {
setL2Angle((prev) => prev + 0.01);
const l2X = L2_RADIUS * Math.cos(l2Angle);
const l2Z = L2_RADIUS * Math.sin(l2Angle);

const jwstX = l2X + JWST_DISTANCE * Math.cos(angle);
const jwstY = JWST_DISTANCE * Math.sin(angle);
const jwstZ = l2Z + JWST_DISTANCE * Math.sin(angle);

jwstRef.current.position.set(jwstX, jwstY, jwstZ);
setJwstPosition({ x: jwstX, y: jwstY, z: jwstZ });
setAngle((prev) => prev + 0.02);
});

return (
<>
<mesh ref={jwstRef}>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color="gold" />
</mesh>
<mesh position={[jwstPosition.x, jwstPosition.y, jwstPosition.z]}>
<torusGeometry args={[JWST_DISTANCE, 0.05, 16, 100]} />
<meshBasicMaterial color="orange" transparent opacity={0.5} />
</mesh>

{/* JWST Label */}
<Html position={[jwstPosition.x, jwstPosition.y + 1, jwstPosition.z]}><div style={{ color: 'rgb(255, 215, 0)' }}>JWST</div></Html>
</>
);
}

// AxisArrows Component
function AxisArrows() {
const arrowLength = 10;
const arrowHeadLength = 1;
const arrowHeadWidth = 0.5;

const xDirection = new THREE.Vector3(1, 0, 0);
const yDirection = new THREE.Vector3(0, 1, 0);
const zDirection = new THREE.Vector3(0, 0, 1);

const xArrow = new THREE.ArrowHelper(xDirection, new THREE.Vector3(0, 0, 0), arrowLength, 0xff0000, arrowHeadLength, arrowHeadWidth);
const yArrow = new THREE.ArrowHelper(yDirection, new THREE.Vector3(0, 0, 0), arrowLength, 0x00ff00, arrowHeadLength, arrowHeadWidth);
const zArrow = new THREE.ArrowHelper(zDirection, new THREE.Vector3(0, 0, 0), arrowLength, 0x0000ff, arrowHeadLength, arrowHeadWidth);

return (
<>
<primitive object={xArrow} />
<primitive object={yArrow} />
<primitive object={zArrow} />
<Html position={[arrowLength, 0, 0]}><div style={{ color: 'red' }}>X</div></Html>
<Html position={[0, arrowLength, 0]}><div style={{ color: 'green' }}>Y</div></Html>
<Html position={[0, 0, arrowLength]}><div style={{ color: 'blue' }}>Z</div></Html>
</>
);
}

// App Component
function App() {
return (
<Canvas
style={{ height: '100vh', width: '100vw' }}
gl={{ alpha: false }}
camera={{ position: [0, 20, 30], fov: 50 }}
onCreated={({ gl }) => {
gl.setClearColor('#000000');
}}
>
<ambientLight />
<pointLight position={[10, 10, 10]} />
<NebulaBackground />
<Stars
radius={70}
depth={30}
count={10000}
factor={10}
saturation={30}
fade={true}
/>
<OrbitControls />
<Sun />
<Earth />
<L2Point />
<JWST />
<AxisArrows />


{/* Post-processing effects */}
<EffectComposer>
<Bloom
intensity={0.5} // Adjust intensity for the bloom effect
width={300} // Resolution width for bloom effect
height={300} // Resolution height for bloom effect
kernelSize={3} // Kernel size for blur
luminanceThreshold={0.3} // Minimum brightness to consider for bloom
luminanceSmoothing={0.7} // Smoothing of the luminance threshold
/>
<DepthOfField
focalLength={0.0002} // Adjust for how blurred background will be
focalDistance={0.1} // Adjust for focal distance
bokehScale={0.1} // Adjust for bokeh scaling
height={480} // Height of the effect
/>
</EffectComposer>
</Canvas>


);
}

export default App;
8 changes: 8 additions & 0 deletions App.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { render, screen } from '@testing-library/react';
import App from './App';

test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
Binary file added EXECUTION PLAN TEAM AETHER.pdf
Binary file not shown.
28 changes: 15 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# NASA Space Apps Challenge 2024 [Noida]

#### Team Name -
#### Problem Statement -
#### Team Leader Email -

## A Brief of the Prototype:
What is your solution? and how it works.

## Code Execution Instruction:
*[If your solution is **not** application based, you can ignore this para]

*The Repository must contain your **Execution Plan PDF**.
# NASA Space Apps Challenge 2024 [Noida]

#### Team Name - Aether
#### Problem Statement - Symphony of the Stars
#### Team Leader Email - [email protected]
#### Website Link - (https://symphonyofstars.netlify.app/)

## A Brief of the Prototype:
A web app integrating original music with interactive 3D animations to bring the James Webb Space Telescope’s discoveries to life. Designed to captivate and educate audiences of all ages, it combines dynamic animations with a custom-composed score to deepen understanding and inspire wonder about the universe.
Textures are used for earth, sun and carina nebula from the Webb Telescope images
## Code Execution Instruction:
*[If your solution is **not** application based, you can ignore this para]
There are all the nodejs codes. The Exceuction Plan PDF is also attached for the idea presentation
This also includes the self composed music track named "Starry Goodbye" if the client blocks the website from playing the audio. Music Componsing files for FL Studio and Musescore are also added

Binary file added Starry Goodbye.flp
Binary file not shown.
Binary file added Starry Goodbye.mp3
Binary file not shown.
Binary file added Starry Goodbye.mscz
Binary file not shown.
Binary file added assets/soundoff.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/soundon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/starrygoodbye.mp3
Binary file not shown.
Binary file added favicon.ico
Binary file not shown.
14 changes: 14 additions & 0 deletions index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}


code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
Loading