File: /home/panomity.de/vr.panomity.com/api/gpuq-sharp-exec.php
<?php
/**
* GPUQ SHARP-Exec: wird vom GPUQ-Worker aufgerufen (job_type vr_sharp_splat).
* POST { _gpuq_secret, pano_id } → erzeugt 360°-Gaussian-Splat der Szene
* (Apple SHARP über die 4 horizontalen Cube-Faces, gemerged).
*/
header('Content-Type: application/json; charset=utf-8');
set_time_limit(1800);
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['ok' => false, 'message' => 'Method not allowed']);
exit;
}
$config = require __DIR__ . '/config.gpuq.php';
$raw = file_get_contents('php://input') ?: '';
$body = json_decode($raw, true);
if (!is_array($body)) {
http_response_code(400);
echo json_encode(['ok' => false, 'message' => 'Invalid JSON payload']);
exit;
}
$secret = (string)($body['_gpuq_secret'] ?? '');
if ($secret === '' || !hash_equals((string)($config['self_exec_secret'] ?? ''), $secret)) {
http_response_code(403);
echo json_encode(['ok' => false, 'message' => 'Forbidden']);
exit;
}
$panoId = (int)($body['pano_id'] ?? 0);
if ($panoId <= 0) {
http_response_code(400);
echo json_encode(['ok' => false, 'message' => 'Invalid pano_id']);
exit;
}
$python = '/home/panomity.de/sharp/.venv/bin/python3';
$script = '/home/panomity.de/sharp/sharp_batch.py';
if (!is_file($python) || !is_file($script)) {
http_response_code(500);
echo json_encode(['ok' => false, 'message' => 'SHARP not installed']);
exit;
}
$cmd = escapeshellarg($python) . ' ' . escapeshellarg($script)
. ' --panos ' . escapeshellarg((string)$panoId) . ' 2>&1';
$output = shell_exec($cmd);
$plyPath = '/home/panomity.de/sharp-out/p' . $panoId . '_360.ply';
if (!is_file($plyPath)) {
http_response_code(502);
echo json_encode([
'ok' => false,
'message' => 'SHARP produced no output',
'log' => mb_substr((string)$output, -800),
]);
exit;
}
// Splat in den Tour-Ordner veröffentlichen.
$publicDir = __DIR__ . '/../panos/p' . $panoId . '.tiles';
$publicPath = $publicDir . '/splat.ply';
if (is_dir($publicDir)) {
@copy($plyPath, $publicPath);
}
echo json_encode([
'ok' => true,
'pano_id' => $panoId,
'ply' => is_file($publicPath) ? ('panos/p' . $panoId . '.tiles/splat.ply') : $plyPath,
'size_bytes' => filesize($plyPath),
], JSON_UNESCAPED_UNICODE);