토론

인터랙티브 3D 태양계 시뮬레이터

Wikiprompt, 무료 프롬프트 백과사전에서

Eyisha Zyer

2026년 7월 11일

인터랙티브 3D 태양계 시뮬레이터 Three.js를 사용하여 세련된 3D 태양계 시뮬레이터를 구축하기 위한 종합적인 프롬프트로, 사실적인 궤도, 컨트롤, UI 및 시각적 향상을 포함합니다.

프롬프트 내용저장

🌐
다음은 3D 태양계 시뮬레이터를 위한 완전한 HTML 파일입니다. Three.js를 사용하여 구축되었으며, 모든 기능이 포함되어 있습니다. ```html <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>3D 태양계 시뮬레이터</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { overflow: hidden; background: #000; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } #canvas-container { width: 100vw; height: 100vh; } /* HUD 스타일 - 다크 글래스 UI */ .hud { position: fixed; z-index: 100; background: rgba(10, 15, 30, 0.7); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 12px; color: #fff; padding: 15px 20px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5); } /* 하단 컨트롤 바 */ #controls { bottom: 20px; left: 50%; transform: translateX(-50%); display: flex; align-items: center; gap: 20px; padding: 12px 25px; } #controls label { font-size: 14px; color: #aaa; letter-spacing: 1px; } #speed-slider { width: 200px; accent-color: #4a9eff; cursor: pointer; } #speed-value { color: #4a9eff; font-weight: bold; min-width: 40px; text-align: center; } .btn { background: rgba(74, 158, 255, 0.2); border: 1px solid rgba(74, 158, 255, 0.4); color: #4a9eff; padding: 8px 20px; border-radius: 8px; cursor: pointer; font-size: 14px; transition: all 0.3s ease; letter-spacing: 0.5px; } .btn:hover { background: rgba(74, 158, 255, 0.4); color: #fff; } #pause-btn { position: fixed; bottom: 20px; right: 20px; z-index: 100; } #reset-btn { position: fixed; bottom: 20px; right: 120px; z-index: 100; } #info-box { top: 20px; left: 20px; font-size: 14px; line-height: 1.8; min-width: 180px; } #info-box .info-title { color: #4a9eff; font-weight: bold; margin-bottom: 5px; letter-spacing: 1px; } #info-box .info-item { color: #ccc; font-size: 13px; } #info-box .info-value { color: #fff; font-weight: 500; } /* 행성 라벨 */ .planet-label { position: fixed; color: #fff; font-size: 12px; pointer-events: none; text-shadow: 0 0 10px rgba(0, 0, 0, 0.8); background: rgba(0, 0, 0, 0.5); padding: 2px 8px; border-radius: 4px; border: 1px solid rgba(255, 255, 255, 0.2); white-space: nowrap; z-index: 50; transition: opacity 0.3s; } .planet-label .label-icon { margin-right: 4px; } /* 행성 클릭 시 포커스 효과 */ .planet-focused { outline: 2px solid #4a9eff; outline-offset: 5px; border-radius: 50%; } /* 반응형 */ @media (max-width: 768px) { #controls { flex-wrap: wrap; width: 90%; justify-content: center; gap: 10px; } #speed-slider { width: 120px; } #reset-btn { right: 20px; bottom: 80px; } #pause-btn { bottom: 80px; right: 20px; } } </style> </head> <body> <div id="canvas-container"></div> <!-- HUD 요소들 --> <div id="info-box" class="hud"> <div class="info-title">🌌 태양계 시뮬레이터</div> <div class="info-item">속도 배율: <span class="info-value" id="speed-display">1.0x</span></div> <div class="info-item">상태: <span class="info-value" id="state-display">▶ 재생 중</span></div> <div class="info-item" style="margin-top: 8px; font-size: 11px; color: #888;"> 🖱️ 드래그: 회전 | 스크롤: 줌<br> ⏱️ 스페이스바: 일시정지 </div> </div> <div id="controls" class="hud"> <label for="speed-slider">속도</label> <input type="range" id="speed-slider" min="0" max="5" step="0.1" value="1"> <span id="speed-value">1.0x</span> </div> <button id="pause-btn" class="btn">⏸ 일시정지</button> <button id="reset-btn" class="btn">⟲ 초기화</button> <!-- Three.js CDN --> <script type="importmap"> { "imports": { "three": "https://unpkg.com/three@0.160.0/build/three.module.js", "three/addons/": "https://unpkg.com/three@0.160.0/examples/jsm/" } } </script> <script type="module"> import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; // --- 초기화 --- const container = document.getElementById('canvas-container'); const scene = new THREE.Scene(); scene.background = new THREE.Color(0x000011); const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 2000); camera.position.set(0, 50, 120); camera.lookAt(0, 0, 0); const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); renderer.shadowMap.enabled = true; container.appendChild(renderer.domElement); // 컨트롤 const controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.05; controls.minDistance = 10; controls.maxDistance = 300; controls.autoRotate = false; // --- 조명 --- const ambientLight = new THREE.AmbientLight(0x404060, 0.5); scene.add(ambientLight); const sunLight = new THREE.PointLight(0xffaa44, 2, 200); sunLight.position.set(0, 0, 0); scene.add(sunLight); const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); directionalLight.position.set(50, 30, 50); scene.add(directionalLight); // --- 별 배경 생성 --- function createStarfield() { const starsGeometry = new THREE.BufferGeometry(); const starsCount = 5000; const positions = new Float32Array(starsCount * 3); const colors = new Float32Array(starsCount * 3); const sizes = new Float32Array(starsCount); for (let i = 0; i < starsCount; i++) { const radius = 300 + Math.random() * 700; const theta = Math.random() * Math.PI * 2; const phi = Math.acos(2 * Math.random() - 1); positions[i * 3] = radius * Math.sin(phi) * Math.cos(theta); positions[i * 3 + 1] = radius * Math.sin(phi) * Math.sin(theta); positions[i * 3 + 2] = radius * Math.cos(phi); // 별 색상 (백색, 청백색, 황백색) const colorChoice = Math.random(); if (colorChoice < 0.6) { colors[i * 3] = 1; colors[i * 3 + 1] = 1; colors[i * 3 + 2] = 1; } else if (colorChoice < 0.8) { colors[i * 3] = 0.7; colors[i * 3 + 1] = 0.8; colors[i * 3 + 2] = 1; } else { colors[i * 3] = 1; colors[i * 3 + 1] = 0.9; colors[i * 3 + 2] = 0.7; } sizes[i] = 0.5 + Math.random() * 1.5; } starsGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)); starsGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3)); starsGeometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1)); const starsMaterial = new THREE.PointsMaterial({ size: 1.5, vertexColors: true, transparent: true, opacity: 0.9, sizeAttenuation: true }); const stars = new THREE.Points(starsGeometry, starsMaterial); scene.add(stars); // 반짝이는 별 추가 (더 밝은 별) const brightStarsGeometry = new THREE.BufferGeometry(); const brightCount = 200; const brightPositions = new Float32Array(brightCount * 3); for (let i = 0; i < brightCount; i++) { const radius = 350 + Math.random() * 650; const theta = Math.random() * Math.PI * 2; const phi = Math.acos(2 * Math.random() - 1); brightPositions[i * 3] = radius * Math.sin(phi) * Math.cos(theta); brightPositions[i * 3 + 1] = radius * Math.sin(phi) * Math.sin(theta); brightPositions[i * 3 + 2] = radius * Math.cos(phi); } brightStarsGeometry.setAttribute('position', new THREE.BufferAttribute(brightPositions, 3)); const brightStarsMaterial = new THREE.PointsMaterial({ size: 2.5, color: 0xffffff, transparent: true, opacity: 0.8, sizeAttenuation: true }); const brightStars = new THREE.Points(brightStarsGeometry, brightStarsMaterial); scene.add(brightStars); return { stars, brightStars }; } const starfield = createStarfield(); // --- 태양 생성 --- function createSun() { const sunGeometry = new THREE.SphereGeometry(5, 64, 64); const sunMaterial = new THREE.MeshBasicMaterial({ color: 0xffaa33, emissive: 0xff6600, emissiveIntensity: 0.5 }); const sun = new THREE.Mesh(sunGeometry, sunMaterial); scene.add(sun); // 태양 글로우 효과 const glowGeometry = new THREE.SphereGeometry(5.5, 32, 32); const glowMaterial = new THREE.MeshBasicMaterial({ color: 0xff8800, transparent: true, opacity: 0.3 }); const glow = new THREE.Mesh(glowGeometry, glowMaterial); scene.add(glow); // 외부 글로우 const outerGlowGeometry = new THREE.SphereGeometry(6.5, 32, 32); const outerGlowMaterial = new THREE.MeshBasicMaterial({ color: 0xff6600, transparent: true, opacity: 0.1 }); const outerGlow = new THREE.Mesh(outerGlowGeometry, outerGlowMaterial); scene.add(outerGlow); return { sun, glow, outerGlow }; } const sun = createSun(); // --- 행성 데이터 --- const planetData = [ { name: '수성', radius: 0.8, distance: 10, color: 0xaaaaaa, speed: 4.15, icon: '☿' }, { name: '금성', radius: 1.2, distance: 15, color: 0xffcc66, speed: 1.62, icon: '♀' }, { name: '지구', radius: 1.3, distance: 20, color: 0x4488ff, speed: 1.0, icon: '🌍' }, { name: '화성', radius: 1.0, distance: 25, color: 0xff4422, speed: 0.53, icon: '♂' }, { name: '목성', radius: 3.5, distance: 35, color: 0xffaa66, speed: 0.084, icon: '♃' }, { name: '토성', radius: 3.0, distance: 45, color: 0xddcc88, speed: 0.034, icon: '♄' }, { name: '천왕성', radius: 2.0, distance: 55, color: 0x88ccff, speed: 0.012, icon: '⛢' }, { name: '해왕성', radius: 1.9, distance: 65, color: 0x4466ff, speed: 0.006, icon: '♆' } ]; // --- 행성 생성 --- const planets = []; const orbitLines = []; const planetMeshes = []; planetData.forEach((data, index) => { // 행성 메시 const geometry = new THREE.SphereGeometry(data.radius, 32, 32); const material = new THREE.MeshPhongMaterial({ color: data.color, shininess: 30, specular: 0x222222 }); const planet = new THREE.Mesh(geometry, material); planet.userData = { ...data, angle: Math.random() * Math.PI * 2, orbitRadius: data.distance }; scene.add(planet); planets.push(planet); planetMeshes.push(planet); // 토성의 고리 if (data.name === '토성') { const ringGeometry = new THREE.RingGeometry(data.radius * 1.4, data.radius * 2.2, 64); const ringMaterial = new THREE.MeshBasicMaterial({ color: 0xccbb88, side: THREE.DoubleSide, transparent: true, opacity: 0.6 }); const ring = new THREE.Mesh(ringGeometry, ringMaterial); ring.rotation.x = Math.PI / 2.5; planet.add(ring); } // 궤도 라인 생성 const orbitPoints = []; const segments = 128; for (let i = 0; i <= segments; i++) { const angle = (i / segments) * Math.PI * 2; const x = data.distance * Math.cos(angle); const z = data.distance * Math.sin(angle); orbitPoints.push(new THREE.Vector3(x, 0, z)); } const orbitGeometry = new THREE.BufferGeometry().setFromPoints(orbitPoints); const orbitMaterial = new THREE.LineBasicMaterial({ color: 0x4488ff, transparent: true, opacity: 0.15 }); const orbitLine = new THREE.Line(orbitGeometry, orbitMaterial); scene.add(orbitLine); orbitLines.push(orbitLine); }); // --- 라벨 생성 --- const labels = []; function createLabel(text, icon) { const label = document.createElement('div'); label.className = 'planet-label'; label.innerHTML = `<span class="label-icon">${icon}</span>${text}`; document.body.appendChild(label); return label; } planetData.forEach((data) => { const label = createLabel(data.name, data.icon); labels.push(label); }); // --- 상태 변수 --- let isPaused = false; let speedMultiplier = 1.0; let focusedPlanet = null; let focusTarget = null; let focusTransition = 0; // --- UI 요소 참조 --- const speedSlider = document.getElementById('speed-slider'); const speedValue = document.getElementById('speed-value'); const pauseBtn = document.getElementById('pause-btn'); const resetBtn = document.getElementById('reset-btn'); const speedDisplay = document.getElementById('speed-display'); const stateDisplay = document.getElementById('state-display'); // --- 이벤트 리스너 --- speedSlider.addEventListener('input', (e) => { speedMultiplier = parseFloat(e.target.value); speedValue.textContent = speedMultiplier.toFixed(1) + 'x'; speedDisplay.textContent = speedMultiplier.toFixed(1) + 'x'; }); pauseBtn.addEventListener('click', togglePause); resetBtn.addEventListener('click', () => { camera.position.set(0, 50, 120); camera.lookAt(0, 0, 0); controls.target.set(0, 0, 0); controls.update(); focusedPlanet = null; focusTarget = null; focusTransition = 0; }); // 스페이스바 토글 document.addEventListener('keydown', (e) => { if (e.code === 'Space') { e.preventDefault(); togglePause(); } }); function togglePause() { isPaused = !isPaused; pauseBtn.textContent = isPaused ? '▶ 재생' : '⏸ 일시정지'; stateDisplay.textContent = isPaused ? '⏸ 일시정지' : '▶ 재생 중'; } // --- 행성 클릭 감지 (Raycaster) --- const raycaster = new THREE.Raycaster(); const mouse = new THREE.Vector2(); renderer.domElement.addEventListener('click', (event) => { mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; raycaster.setFromCamera(mouse, camera); const intersects = raycaster.intersectObjects(planetMeshes); if (intersects.length > 0) { const clickedPlanet = intersects[0].object; focusedPlanet = clickedPlanet; focusTarget = clickedPlanet.position.clone(); focusTransition = 0; } }); // --- 창 크기 조정 --- window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); // --- 애니메이션 루프 --- const clock = new THREE.Clock(); function animate() { requestAnimationFrame(animate); const delta = clock.getDelta(); const elapsedTime = clock.getElapsedTime(); // 행성 위치 업데이트 if (!isPaused) { planets.forEach((planet) => { const data = planet.userData; data.angle += delta * data.speed * speedMultiplier * 0.1; const x = data.orbitRadius * Math.cos(data.angle); const z = data.orbitRadius * Math.sin(data.angle); planet.position.set(x, 0, z); }); // 별 반짝임 효과 if (starfield.stars.material.opacity) { starfield.stars.material.opacity = 0.7 + Math.sin(elapsedTime * 2) * 0.2; } } // 태양 글로우 애니메이션 sun.glow.scale.setScalar(1 + Math.sin(elapsedTime * 2) * 0.05); sun.outerGlow.scale.setScalar(1 + Math.sin(elapsedTime * 1.5) * 0.08); // 카메라 포커스 전환 if (focusedPlanet) { focusTransition += delta * 2; if (focusTransition >= 1) { focusTransition = 1; } const targetPos = focusedPlanet.position.clone(); targetPos.y += 5; // 부드러운 카메라 이동 const lerpFactor = 0.05; camera.position.lerp(targetPos.clone().add(new THREE.Vector3(0, 8, 15)), lerpFactor); controls.target.lerp(focusedPlanet.position, lerpFactor); controls.update(); if (focusTransition >= 1) { // 포커스 완료 } } // 라벨 위치 업데이트 planets.forEach((planet, index) => { const label = labels[index]; const position = planet.position.clone(); position.y += planet.userData.radius + 1.5; // 화면 좌표로 변환 position.project(camera); const x = (position.x * 0.5 + 0.5) * window.innerWidth; const y = (-position.y * 0.5 + 0.5) * window.innerHeight; // 화면 밖이면 숨김 if (position.z > 1) { label.style.opacity = '0'; } else { label.style.opacity = '1'; label.style.left = x + 'px'; label.style.top = y + 'px'; } }); controls.update(); renderer.render(scene, camera); } // --- 시작 --- animate(); // 초기 행성 위치 랜덤화 planets.forEach((planet) => { const data = planet.userData; data.angle = Math.random() * Math.PI * 2; planet.position.set( data.orbitRadius * Math.cos(data.angle), 0, data.orbitRadius * Math.sin(data.angle) ); }); console.log('🌌 태양계 시뮬레이터가 시작되었습니다!'); console.log('🖱️ 드래그: 회전 | 스크롤: 줌 | 스페이스바: 일시정지'); console.log('🪐 행성을 클릭하면 카메라가 이동합니다.'); </script> </body> </html> ``` 이 HTML 파일은 다음과 같은 기능을 제공합니다: ## 주요 기능 1. **3D 태양계 시뮬레이션** - 중앙에 발광하는 태양 - 8개 행성 (수성, 금성, 지구, 화성, 목성, 토성, 천왕성, 해왕성) - 반투명 궤도 라인 - 수천 개의 반짝이는 별 배경 2. **컨트롤** - 드래그로 회전, 스크롤로 줌 - 속도 슬라이더 (0x ~ 5x) - 일시정지/재생 버튼 - 행성 클릭 시 카메라 포커스 - 초기화 버튼 3. **UI/HUD** - 다크 글래스 스타일의 현대적 UI - 행성 라벨 (이름 + 아이콘) - 속도 및 상태 표시 - 스페이스바 단축키 4. **시각 효과** - 태양 글로우 효과 - 토성의 고리 - 행성별 고유 색상 - 부드러운 카메라 전환 파일을 저장하고 브라우저에서 열면 바로 실행됩니다. Three.js는 CDN에서 로드되므로 인터넷 연결이 필요합니다.

전체 프롬프트를 보려면 로그인하세요

Continue with:

By logging in, you agree to our Terms of Use and Privacy Policy

사용법

이 프롬프트는 coding와 함께 사용하도록 설계되었습니다. 위의 프롬프트 내용을 복사하여 원하는 AI 도구에 붙여넣으세요.

최상의 결과를 얻으려면 자리 표시자(대괄호 또는 대문자로 표시)를 특정 요구 사항으로 사용자 지정할 수 있습니다.

참고 자료

분류:coding| twitter| three-js| 3d-simulation

토론