|
1 | | -// 3D Solar System Initialization |
2 | | -let scene, camera, renderer, controls; |
3 | | -const planets = []; |
4 | | -const planetData = [ |
5 | | - { name: 'Mercury', color: 0x808080, size: 0.4, distance: 8 }, |
6 | | - { name: 'Venus', color: 0xffd700, size: 0.9, distance: 11 }, |
7 | | - { name: 'Earth', color: 0x0000ff, size: 1, distance: 15 }, |
8 | | - { name: 'Mars', color: 0xff0000, size: 0.5, distance: 20 }, |
9 | | - { name: 'Jupiter', color: 0xffa500, size: 2.5, distance: 28 }, |
10 | | - { name: 'Saturn', color: 0xffd700, size: 2, distance: 35 }, |
11 | | - { name: 'Uranus', color: 0x00ffff, size: 1.5, distance: 40 }, |
12 | | - { name: 'Neptune', color: 0x0000ff, size: 1.5, distance: 45 } |
13 | | -]; |
14 | 1 |
|
15 | | -function initSolarSystem() { |
16 | | - // Three.js setup |
17 | | - scene = new THREE.Scene(); |
18 | | - camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); |
19 | | - renderer = new THREE.WebGLRenderer({ antialias: true }); |
20 | | - renderer.setSize(window.innerWidth, window.innerHeight); |
21 | | - document.body.appendChild(renderer.domElement); |
22 | | - |
23 | | - // Lighting |
24 | | - const light = new THREE.PointLight(0xffffff, 1.5); |
25 | | - scene.add(light); |
26 | | - |
27 | | - // Create Sun |
28 | | - const sun = new THREE.Mesh( |
29 | | - new THREE.SphereGeometry(5, 32, 32), |
30 | | - new THREE.MeshBasicMaterial({ color: 0xffff00 }) |
31 | | - ); |
32 | | - scene.add(sun); |
33 | | - |
34 | | - // Create Planets |
35 | | - planetData.forEach(data => { |
36 | | - const planet = new THREE.Mesh( |
37 | | - new THREE.SphereGeometry(data.size, 32, 32), |
38 | | - new THREE.MeshPhongMaterial({ color: data.color }) |
39 | | - ); |
40 | | - planet.position.x = data.distance; |
41 | | - scene.add(planet); |
42 | | - planets.push({ |
43 | | - mesh: planet, |
44 | | - ...data, |
45 | | - angle: Math.random() * Math.PI * 2 |
46 | | - }); |
47 | | - }); |
48 | | - |
49 | | - // Camera and Controls |
50 | | - camera.position.z = 50; |
51 | | - controls = new THREE.OrbitControls(camera, renderer.domElement); |
52 | | - controls.enableDamping = true; |
53 | | - controls.dampingFactor = 0.05; |
54 | | - |
55 | | - // Planet Click Handler |
56 | | - const raycaster = new THREE.Raycaster(); |
57 | | - const mouse = new THREE.Vector2(); |
58 | | - window.addEventListener('click', (event) => { |
59 | | - mouse.set( |
60 | | - (event.clientX / window.innerWidth) * 2 - 1, |
61 | | - -(event.clientY / window.innerHeight) * 2 + 1 |
62 | | - ); |
63 | | - raycaster.setFromCamera(mouse, camera); |
64 | | - const intersects = raycaster.intersectObjects(planets.map(p => p.mesh)); |
65 | | - |
66 | | - if (intersects.length > 0) { |
67 | | - const planet = planets.find(p => p.mesh === intersects[0].object); |
68 | | - const chatMessages = document.getElementById('chat-messages'); |
69 | | - chatMessages.innerHTML += ` |
70 | | - <div class="chat-message system-message"> |
71 | | - 🌍 <b>${planet.name}</b><br> |
72 | | - Size: ${planet.size}x Earth radius<br> |
73 | | - Orbital Distance: ${planet.distance} AU |
74 | | - </div>`; |
75 | | - chatMessages.scrollTop = chatMessages.scrollHeight; |
76 | | - } |
77 | | - }); |
78 | | - |
79 | | - animate(); |
80 | | -} |
81 | | - |
82 | | -// Animation Loop |
83 | | -function animate() { |
84 | | - requestAnimationFrame(animate); |
85 | | - planets.forEach(planet => { |
86 | | - planet.angle += 0.005; |
87 | | - planet.mesh.position.x = Math.cos(planet.angle) * planet.distance; |
88 | | - planet.mesh.position.z = Math.sin(planet.angle) * planet.distance; |
89 | | - }); |
90 | | - controls.update(); |
91 | | - renderer.render(scene, camera); |
92 | | -} |
93 | | - |
94 | | -// AI Chat Functions |
95 | | -async function sendChat() { |
96 | | - const apiKey = document.getElementById('api-key').value.trim(); |
97 | | - const userInput = document.getElementById('user-input').value.trim(); |
98 | | - if (!apiKey) return alert('🔑 Please enter your API key'); |
99 | | - if (!userInput) return alert('🚀 Please enter a space-related question'); |
100 | | - |
101 | | - const chatMessages = document.getElementById('chat-messages'); |
102 | | - const loading = document.getElementById('loading'); |
103 | | - |
104 | | - // Add user message |
105 | | - chatMessages.innerHTML += ` |
106 | | - <div class="chat-message"> |
107 | | - 👨🚀 <b>You:</b> ${userInput} |
108 | | - </div>`; |
109 | | - |
110 | | - loading.style.display = 'block'; |
111 | | - document.getElementById('user-input').value = ''; |
112 | | - |
113 | | - try { |
114 | | - // API Request |
115 | | - const response = await fetch( |
116 | | - `https://us-central1-aiplatform.googleapis.com/v1/projects/YOUR_PROJECT_ID/locations/us-central1/publishers/google/models/gemini-pro:generateContent?key=${apiKey}`, |
117 | | - { |
118 | | - method: 'POST', |
119 | | - headers: { 'Content-Type': 'application/json' }, |
120 | | - body: JSON.stringify({ |
121 | | - contents: [{ |
122 | | - parts: [{ |
123 | | - text: `As an astronomy expert, answer concisely in markdown. Use code formatting for equations and technical terms. Question: ${userInput}` |
124 | | - }] |
125 | | - }], |
126 | | - safety_settings: [{ |
127 | | - category: "HARM_CATEGORY_DANGEROUS_CONTENT", |
128 | | - threshold: "BLOCK_ONLY_HIGH" |
129 | | - }] |
130 | | - }) |
131 | | - } |
132 | | - ); |
133 | | - |
134 | | - if (!response.ok) throw new Error(`API Error: ${response.status}`); |
135 | | - const data = await response.json(); |
136 | | - |
137 | | - // Format response |
138 | | - let botResponse = data.candidates?.[0]?.content?.parts?.[0]?.text |
139 | | - || "🌌 Hmm, the cosmos seems quiet... No response received."; |
140 | | - |
141 | | - // Convert markdown code blocks to HTML |
142 | | - botResponse = botResponse |
143 | | - .replace(/```(\w+)?\n([^```]+)```/g, '<pre>$2</pre>') |
144 | | - .replace(/`([^`]+)`/g, '<code>$1</code>'); |
145 | | - |
146 | | - // Add AI response |
147 | | - chatMessages.innerHTML += ` |
148 | | - <div class="chat-message"> |
149 | | - 🤖 <b>AI Astronomer:</b> ${botResponse} |
150 | | - </div>`; |
151 | | - |
152 | | - } catch (error) { |
153 | | - console.error('Error:', error); |
154 | | - chatMessages.innerHTML += ` |
155 | | - <div class="chat-message" style="color: #ff4444"> |
156 | | - ❌ <b>Error:</b> ${error.message} |
157 | | - </div>`; |
158 | | - } finally { |
159 | | - loading.style.display = 'none'; |
160 | | - chatMessages.scrollTop = chatMessages.scrollHeight; |
161 | | - } |
162 | | -} |
163 | | - |
164 | | -// Initialize and Event Listeners |
165 | | -window.onload = initSolarSystem; |
166 | | -window.addEventListener('resize', () => { |
167 | | - camera.aspect = window.innerWidth / window.innerHeight; |
168 | | - camera.updateProjectionMatrix(); |
169 | | - renderer.setSize(window.innerWidth, window.innerHeight); |
170 | | -}); |
171 | | -document.getElementById('user-input').addEventListener('keypress', (e) => { |
172 | | - if (e.key === 'Enter') sendChat(); |
173 | | -}); |
0 commit comments