Mars eingebaut und Texturen verbessert
@@ -61,6 +61,7 @@ function manageablePublicPages(): array
|
|||||||
'astronomical_conversions.php' => 'Astronomical Conversions',
|
'astronomical_conversions.php' => 'Astronomical Conversions',
|
||||||
'tcrb_lightcurve.php' => 'T CrB Lichtkurve',
|
'tcrb_lightcurve.php' => 'T CrB Lichtkurve',
|
||||||
'solarsystem.php' => 'Sonnensystem',
|
'solarsystem.php' => 'Sonnensystem',
|
||||||
|
'mars.php' => 'Mars',
|
||||||
'jupitersystem.php' => 'Jupitersystem',
|
'jupitersystem.php' => 'Jupitersystem',
|
||||||
'tagbogen.php' => 'Tagbogen',
|
'tagbogen.php' => 'Tagbogen',
|
||||||
'sternenhimmel.php' => 'Sternenhimmel',
|
'sternenhimmel.php' => 'Sternenhimmel',
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/auth_helpers.php';
|
require_once __DIR__ . '/auth_helpers.php';
|
||||||
|
if (!isset($loggedIn)) {
|
||||||
|
$loggedIn = isset($_SESSION['user_id']);
|
||||||
|
}
|
||||||
|
|
||||||
$title = isset($pageTitle) && is_string($pageTitle) && $pageTitle !== ''
|
$title = isset($pageTitle) && is_string($pageTitle) && $pageTitle !== ''
|
||||||
? $pageTitle
|
? $pageTitle
|
||||||
: 'Skyview & AstroTools - Astronomiemuseum der Sternwarte Sonneberg';
|
: 'Skyview & AstroTools - Astronomiemuseum der Sternwarte Sonneberg';
|
||||||
@@ -123,6 +127,7 @@ $menuGroups = [
|
|||||||
['href' => 'astronomical_conversions.php', 'label' => 'Astronomical Conversions'],
|
['href' => 'astronomical_conversions.php', 'label' => 'Astronomical Conversions'],
|
||||||
['href' => 'tcrb_lightcurve.php', 'label' => 'T CrB Lichtkurve'],
|
['href' => 'tcrb_lightcurve.php', 'label' => 'T CrB Lichtkurve'],
|
||||||
['href' => 'solarsystem.php', 'label' => 'Sonnensystem'],
|
['href' => 'solarsystem.php', 'label' => 'Sonnensystem'],
|
||||||
|
['href' => 'mars.php', 'label' => 'Mars'],
|
||||||
['href' => 'jupitersystem.php', 'label' => 'Jupitersystem'],
|
['href' => 'jupitersystem.php', 'label' => 'Jupitersystem'],
|
||||||
['href' => 'tagbogen.php', 'label' => 'Tagbogen'],
|
['href' => 'tagbogen.php', 'label' => 'Tagbogen'],
|
||||||
['href' => 'sternenhimmel.php', 'label' => 'Sternenhimmel'],
|
['href' => 'sternenhimmel.php', 'label' => 'Sternenhimmel'],
|
||||||
@@ -178,9 +183,9 @@ if ($loggedIn && !$hasFullAdminAccess && $pdoHeader !== null) {
|
|||||||
foreach ($menuGroups as &$group) {
|
foreach ($menuGroups as &$group) {
|
||||||
$group['links'] = array_values(array_filter(
|
$group['links'] = array_values(array_filter(
|
||||||
$group['links'],
|
$group['links'],
|
||||||
static function (array $link) use ($allowedPageKeys): bool {
|
static function (array $link) use ($allowedPageKeys, $publicAccessAllowlist): bool {
|
||||||
$href = trim((string) ($link['href'] ?? ''));
|
$href = trim((string) ($link['href'] ?? ''));
|
||||||
return $href !== '' && isset($allowedPageKeys[$href]);
|
return $href !== '' && (isset($allowedPageKeys[$href]) || in_array($href, $publicAccessAllowlist, true));
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -193,9 +198,9 @@ if ($loggedIn && !$hasFullAdminAccess && $pdoHeader !== null) {
|
|||||||
|
|
||||||
$accountLinks = array_values(array_filter(
|
$accountLinks = array_values(array_filter(
|
||||||
$accountLinks,
|
$accountLinks,
|
||||||
static function (array $link) use ($allowedPageKeys): bool {
|
static function (array $link) use ($allowedPageKeys, $publicAccessAllowlist): bool {
|
||||||
$href = trim((string) ($link['href'] ?? ''));
|
$href = trim((string) ($link['href'] ?? ''));
|
||||||
return $href !== '' && isset($allowedPageKeys[$href]);
|
return $href !== '' && (isset($allowedPageKeys[$href]) || in_array($href, $publicAccessAllowlist, true));
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 198 KiB After Width: | Height: | Size: 186 KiB |
|
Before Width: | Height: | Size: 686 KiB After Width: | Height: | Size: 648 KiB |
|
Before Width: | Height: | Size: 2.5 MiB After Width: | Height: | Size: 2.2 MiB |
|
Before Width: | Height: | Size: 8.0 MiB After Width: | Height: | Size: 7.1 MiB |
|
After Width: | Height: | Size: 2.4 MiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 236 KiB |
@@ -0,0 +1,240 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
ini_set('display_errors', '1');
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
$pageTitle = 'Mars - AstroTools';
|
||||||
|
$bodyClass = 'mars-page';
|
||||||
|
$headerIntroPre = 'Planetendarstellung';
|
||||||
|
$headerIntroTitle = 'Mars';
|
||||||
|
$headerIntroSub = 'Eine einfache 3D-Ansicht mit Marstextur.';
|
||||||
|
?>
|
||||||
|
<?php require __DIR__ . '/header.php'; ?>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.mars-stage-card {
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mars-stage {
|
||||||
|
position: relative;
|
||||||
|
min-height: 70vh;
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at top, rgba(255, 153, 102, 0.12), transparent 40%),
|
||||||
|
linear-gradient(180deg, rgba(14, 10, 10, 0.94), rgba(8, 8, 12, 0.98));
|
||||||
|
}
|
||||||
|
|
||||||
|
#marsViewport {
|
||||||
|
width: 100%;
|
||||||
|
height: 70vh;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mars-overlay {
|
||||||
|
position: absolute;
|
||||||
|
left: 1rem;
|
||||||
|
bottom: 1rem;
|
||||||
|
padding: 0.6rem 0.85rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(15, 15, 22, 0.72);
|
||||||
|
color: #f4e7de;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.mars-stage,
|
||||||
|
#marsViewport {
|
||||||
|
height: 58vh;
|
||||||
|
min-height: 420px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<section class="card mars-stage-card">
|
||||||
|
<div class="mars-stage">
|
||||||
|
<canvas id="marsViewport" aria-label="3D-Ansicht des Mars"></canvas>
|
||||||
|
<div class="mars-overlay">Ziehen zum Drehen, Mausrad zum Zoomen</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<script type="module">
|
||||||
|
let THREE;
|
||||||
|
|
||||||
|
async function initMars() {
|
||||||
|
THREE = await import('./js/three.module.js');
|
||||||
|
|
||||||
|
const canvas = document.getElementById('marsViewport');
|
||||||
|
if (!canvas) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderer = new THREE.WebGLRenderer({
|
||||||
|
canvas,
|
||||||
|
antialias: true,
|
||||||
|
alpha: true
|
||||||
|
});
|
||||||
|
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2));
|
||||||
|
renderer.outputColorSpace = THREE.SRGBColorSpace;
|
||||||
|
renderer.shadowMap.enabled = true;
|
||||||
|
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
||||||
|
renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
||||||
|
renderer.toneMappingExposure = 1.05;
|
||||||
|
|
||||||
|
const scene = new THREE.Scene();
|
||||||
|
|
||||||
|
const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
|
||||||
|
camera.position.set(0, 0, 4.8);
|
||||||
|
|
||||||
|
const hemisphereLight = new THREE.HemisphereLight(0x9db4d8, 0x120d0b, 0.16);
|
||||||
|
scene.add(hemisphereLight);
|
||||||
|
|
||||||
|
const sunLight = new THREE.DirectionalLight(0xfff1d6, 2.8);
|
||||||
|
sunLight.position.set(7, 1.8, 5.5);
|
||||||
|
sunLight.castShadow = true;
|
||||||
|
sunLight.shadow.mapSize.set(2048, 2048);
|
||||||
|
sunLight.shadow.bias = -0.0008;
|
||||||
|
sunLight.shadow.normalBias = 0.02;
|
||||||
|
sunLight.shadow.camera.near = 1;
|
||||||
|
sunLight.shadow.camera.far = 20;
|
||||||
|
sunLight.shadow.camera.left = -4;
|
||||||
|
sunLight.shadow.camera.right = 4;
|
||||||
|
sunLight.shadow.camera.top = 4;
|
||||||
|
sunLight.shadow.camera.bottom = -4;
|
||||||
|
sunLight.target.position.set(0, 0, 0);
|
||||||
|
scene.add(sunLight);
|
||||||
|
scene.add(sunLight.target);
|
||||||
|
|
||||||
|
const fillLight = new THREE.DirectionalLight(0xa4b4d8, 0.18);
|
||||||
|
fillLight.position.set(-4, -1.5, -3.5);
|
||||||
|
scene.add(fillLight);
|
||||||
|
|
||||||
|
const loader = new THREE.TextureLoader();
|
||||||
|
const marsTexture = loader.load('./images/planets/mars_4096.jpg');
|
||||||
|
marsTexture.colorSpace = THREE.SRGBColorSpace;
|
||||||
|
marsTexture.anisotropy = renderer.capabilities.getMaxAnisotropy();
|
||||||
|
const marsDisplacement = loader.load('./images/planets/mars_displacement_5760.jpg');
|
||||||
|
marsDisplacement.anisotropy = renderer.capabilities.getMaxAnisotropy();
|
||||||
|
|
||||||
|
const geometry = new THREE.SphereGeometry(1.45, 192, 192);
|
||||||
|
const material = new THREE.MeshStandardMaterial({
|
||||||
|
map: marsTexture,
|
||||||
|
displacementMap: marsDisplacement,
|
||||||
|
displacementScale: 0.065,
|
||||||
|
displacementBias: -0.02,
|
||||||
|
bumpMap: marsDisplacement,
|
||||||
|
bumpScale: 0.03,
|
||||||
|
roughness: 0.96,
|
||||||
|
metalness: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
const mars = new THREE.Mesh(geometry, material);
|
||||||
|
mars.castShadow = true;
|
||||||
|
mars.receiveShadow = true;
|
||||||
|
scene.add(mars);
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
isPointerDown: false,
|
||||||
|
lastX: 0,
|
||||||
|
lastY: 0,
|
||||||
|
velocityX: 0,
|
||||||
|
velocityY: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
canvas.style.touchAction = 'none';
|
||||||
|
|
||||||
|
function resizeRenderer() {
|
||||||
|
const width = canvas.clientWidth;
|
||||||
|
const height = canvas.clientHeight;
|
||||||
|
if (width === 0 || height === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.setSize(width, height, false);
|
||||||
|
camera.aspect = width / height;
|
||||||
|
camera.updateProjectionMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clampCameraDistance(nextZ) {
|
||||||
|
return Math.min(Math.max(nextZ, 3.2), 8.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPointerDown(event) {
|
||||||
|
state.isPointerDown = true;
|
||||||
|
state.lastX = event.clientX;
|
||||||
|
state.lastY = event.clientY;
|
||||||
|
canvas.setPointerCapture(event.pointerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPointerMove(event) {
|
||||||
|
if (!state.isPointerDown) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const deltaX = event.clientX - state.lastX;
|
||||||
|
const deltaY = event.clientY - state.lastY;
|
||||||
|
state.lastX = event.clientX;
|
||||||
|
state.lastY = event.clientY;
|
||||||
|
|
||||||
|
const rotationSpeed = 0.008;
|
||||||
|
mars.rotation.y += deltaX * rotationSpeed;
|
||||||
|
mars.rotation.x += deltaY * rotationSpeed;
|
||||||
|
mars.rotation.x = Math.max(-1.25, Math.min(1.25, mars.rotation.x));
|
||||||
|
|
||||||
|
state.velocityX = deltaX * 0.0009;
|
||||||
|
state.velocityY = deltaY * 0.0009;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPointerUp(event) {
|
||||||
|
state.isPointerDown = false;
|
||||||
|
if (canvas.hasPointerCapture(event.pointerId)) {
|
||||||
|
canvas.releasePointerCapture(event.pointerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onWheel(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
camera.position.z = clampCameraDistance(camera.position.z + event.deltaY * 0.0035);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderFrame() {
|
||||||
|
if (!state.isPointerDown) {
|
||||||
|
mars.rotation.y += state.velocityX;
|
||||||
|
mars.rotation.x += state.velocityY;
|
||||||
|
mars.rotation.x = Math.max(-1.25, Math.min(1.25, mars.rotation.x));
|
||||||
|
state.velocityX *= 0.94;
|
||||||
|
state.velocityY *= 0.94;
|
||||||
|
|
||||||
|
if (Math.abs(state.velocityX) < 0.00001) {
|
||||||
|
state.velocityX = 0;
|
||||||
|
}
|
||||||
|
if (Math.abs(state.velocityY) < 0.00001) {
|
||||||
|
state.velocityY = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.render(scene, camera);
|
||||||
|
requestAnimationFrame(renderFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.addEventListener('pointerdown', onPointerDown);
|
||||||
|
canvas.addEventListener('pointermove', onPointerMove);
|
||||||
|
canvas.addEventListener('pointerup', onPointerUp);
|
||||||
|
canvas.addEventListener('pointercancel', onPointerUp);
|
||||||
|
canvas.addEventListener('wheel', onWheel, { passive: false });
|
||||||
|
|
||||||
|
window.addEventListener('resize', resizeRenderer);
|
||||||
|
resizeRenderer();
|
||||||
|
renderFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
initMars().catch((error) => {
|
||||||
|
console.error('Mars-Ansicht konnte nicht initialisiert werden.', error);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<?php require __DIR__ . '/footer.php'; ?>
|
||||||