This commit is contained in:
legop3
2026-06-07 04:34:27 -04:00
parent adedc945f0
commit 8356d37364
5 changed files with 58 additions and 67 deletions
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -11,7 +11,7 @@
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="Roomba Rover" /> <meta name="apple-mobile-web-app-title" content="Roomba Rover" />
<title>Roomba Rover</title> <title>Roomba Rover</title>
<script type="module" crossorigin src="/assets/index-DlSNvZve.js"></script> <script type="module" crossorigin src="/assets/index-cdQmQokE.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-Dzjs7qyo.css"> <link rel="stylesheet" crossorigin href="/assets/index-Dzjs7qyo.css">
</head> </head>
<body> <body>
@@ -38,7 +38,7 @@ constexpr int kRgbBytes = kWidth * kHeight * 3;
constexpr int kDepthPixels = kWidth * kHeight; constexpr int kDepthPixels = kWidth * kHeight;
constexpr int kFrameStaleMs = 5000; constexpr int kFrameStaleMs = 5000;
constexpr int kCommandFrameWaitMs = 3000; constexpr int kCommandFrameWaitMs = 3000;
constexpr int kDepthHistoryFrames = 1000; constexpr int kDepthHistoryFrames = 100;
constexpr int kDepthMinimumValidSamples = 5; constexpr int kDepthMinimumValidSamples = 5;
struct FrameCache { struct FrameCache {
@@ -37,25 +37,25 @@ export default function PointCloudViewer({ frame }) {
const THREE = threeRef.current; const THREE = threeRef.current;
if (!scene || !THREE || !currentFrame?.buffer || !visibleRef.current) return; if (!scene || !THREE || !currentFrame?.buffer || !visibleRef.current) return;
const pointCount = Number(currentFrame.meta?.pointCount) || 0;
const strideBytes = Number(currentFrame.meta?.strideBytes) || 16; const strideBytes = Number(currentFrame.meta?.strideBytes) || 16;
if (!pointCount || strideBytes < 16) return;
const view = new DataView(currentFrame.buffer);
const width = Number(currentFrame.meta?.width) || 0; const width = Number(currentFrame.meta?.width) || 0;
const height = Number(currentFrame.meta?.height) || 0; const height = Number(currentFrame.meta?.height) || 0;
const gridPointCount = width * height; const gridPointCount = width * height;
const isGridFrame = Boolean(currentFrame.meta?.grid) && gridPointCount > 0; if (!currentFrame.meta?.grid || !gridPointCount || strideBytes < 16) {
const vertexCount = isGridFrame ? gridPointCount : pointCount; disposeRenderedObject();
const positions = new Float32Array(vertexCount * 3); return;
const colors = new Float32Array(vertexCount * 3); }
const valid = isGridFrame ? new Uint8Array(vertexCount) : null;
const zValues = isGridFrame ? new Float32Array(vertexCount) : null; const view = new DataView(currentFrame.buffer);
const positions = new Float32Array(gridPointCount * 3);
const colors = new Float32Array(gridPointCount * 3);
const valid = new Uint8Array(gridPointCount);
const zValues = new Float32Array(gridPointCount);
// The server sends x/y/z as little-endian floats followed by rgba bytes. // The server sends x/y/z as little-endian floats followed by rgba bytes.
// Building typed arrays only when the canvas is visible keeps expensive // Building typed arrays only when the canvas is visible keeps expensive
// browser-side point conversion from happening while the card is off-screen. // browser-side point conversion from happening while the card is off-screen.
for (let index = 0; index < vertexCount; index += 1) { for (let index = 0; index < gridPointCount; index += 1) {
const source = index * strideBytes; const source = index * strideBytes;
const target = index * 3; const target = index * 3;
positions[target + 0] = view.getFloat32(source + 0, true); positions[target + 0] = view.getFloat32(source + 0, true);
@@ -65,18 +65,14 @@ export default function PointCloudViewer({ frame }) {
colors[target + 0] = view.getUint8(source + 12) / 255; colors[target + 0] = view.getUint8(source + 12) / 255;
colors[target + 1] = view.getUint8(source + 13) / 255; colors[target + 1] = view.getUint8(source + 13) / 255;
colors[target + 2] = view.getUint8(source + 14) / 255; colors[target + 2] = view.getUint8(source + 14) / 255;
if (isGridFrame) {
valid[index] = view.getUint8(source + 15) > 0 ? 1 : 0; valid[index] = view.getUint8(source + 15) > 0 ? 1 : 0;
zValues[index] = z; zValues[index] = z;
} }
}
const geometry = new THREE.BufferGeometry(); const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)); geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3)); geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
let object = null;
if (isGridFrame) {
const indices = []; const indices = [];
const maxDepthStepMeters = 0.12; const maxDepthStepMeters = 0.12;
const canConnect = (a, b, c) => { const canConnect = (a, b, c) => {
@@ -107,15 +103,7 @@ export default function PointCloudViewer({ frame }) {
vertexColors: true, vertexColors: true,
side: THREE.DoubleSide, side: THREE.DoubleSide,
}); });
object = new THREE.Mesh(geometry, material); const object = new THREE.Mesh(geometry, material);
} else {
const material = new THREE.PointsMaterial({
size: 0.018,
vertexColors: true,
sizeAttenuation: true,
});
object = new THREE.Points(geometry, material);
}
geometry.computeBoundingSphere(); geometry.computeBoundingSphere();
disposeRenderedObject(); disposeRenderedObject();
+4 -1
View File
@@ -31,7 +31,10 @@ export default function KinectPanel() {
const handlePointCloudFrame = (meta = {}, buffer) => { const handlePointCloudFrame = (meta = {}, buffer) => {
const normalized = normalizeBinaryPayload(buffer); const normalized = normalizeBinaryPayload(buffer);
if (!normalized) return; // The current 3D viewer only supports grid frames because the mesh needs
// the original Kinect pixel layout. Ignore old packed-point cached
// frames so they cannot silently render as the retired dot-cloud view.
if (!normalized || !meta?.grid) return;
setPointCloudFrame({ meta, buffer: normalized }); setPointCloudFrame({ meta, buffer: normalized });
setActiveView('3d'); setActiveView('3d');
setRequestError(null); setRequestError(null);