beam: restore point cloud source colors

This commit is contained in:
CODEX 2026-06-05 00:22:28 +03:00
parent ff994e705d
commit bf397ff191
2 changed files with 98 additions and 1 deletions

View File

@ -215,6 +215,7 @@ let gizmo = null;
const transformStore = {}; // modelId -> objectId -> {position, rotation, scale}
const modelTypes = {}; // modelId -> normalized type
const sceneModels = {}; // modelId -> SceneModel
const pointCloudColorSnapshots = new Map(); // modelId -> [{ layer, colors, workingColors }]
let activeDisplayMode = "source";
let activeLightingMode = "ambient";
let activeNavigationAxis = "auto";
@ -443,6 +444,92 @@ const getBaseEdgesForModel = (modelId) => {
const isPointCloudModel = (modelId) => modelTypes[modelId] === "las";
const getPointCloudLayers = (model) => (
(model?.layerList || []).filter((layer) => (
layer?.primitive === "points" &&
layer?._state?.colorsBuf?.getData &&
layer?._state?.colorsBuf?.setData
))
);
const snapshotPointCloudColors = (modelId) => {
const model = sceneModels[modelId] || viewer?.scene?.models?.[modelId];
if (!model || !isPointCloudModel(modelId) || pointCloudColorSnapshots.has(modelId)) return;
const snapshots = getPointCloudLayers(model)
.map((layer) => {
try {
const colors = layer._state.colorsBuf.getData();
return colors?.length ? { layer, colors, workingColors: null } : null;
} catch (err) {
console.warn("point cloud color snapshot failed", err);
return null;
}
})
.filter(Boolean);
if (snapshots.length) {
pointCloudColorSnapshots.set(modelId, snapshots);
}
};
const clearPointCloudEntityColorState = (targets) => {
targets.forEach((entity) => {
if (!entity) return;
try {
entity.xrayed = false;
entity.opacity = 1;
entity.edges = false;
(entity.meshes || []).forEach((mesh) => {
mesh._colorizing = false;
});
if (entity._colorizeUpdated && viewer?.scene?._objectColorizeUpdated) {
viewer.scene._objectColorizeUpdated(entity, false);
entity._colorizeUpdated = false;
}
} catch (err) {
console.warn("point cloud entity reset failed", err);
}
});
};
const writePointCloudColors = (modelId, colorize = null) => {
snapshotPointCloudColors(modelId);
const snapshots = pointCloudColorSnapshots.get(modelId) || [];
const color = colorize
? colorize.map((v) => Math.max(0, Math.min(255, Math.round(v * 255))))
: null;
snapshots.forEach((snapshot) => {
const colorsBuf = snapshot.layer?._state?.colorsBuf;
if (!colorsBuf?.setData) return;
try {
if (!color) {
colorsBuf.setData(snapshot.colors);
return;
}
const original = snapshot.colors;
const working = snapshot.workingColors?.length === original.length
? snapshot.workingColors
: new Uint8Array(original.length);
for (let i = 0; i < original.length; i += 4) {
working[i] = color[0];
working[i + 1] = color[1];
working[i + 2] = color[2];
working[i + 3] = original[i + 3];
}
snapshot.workingColors = working;
colorsBuf.setData(working);
} catch (err) {
console.warn("point cloud color restore failed", err);
}
});
};
const applyPointCloudDisplayMode = (modelId, preset, targets) => {
clearPointCloudEntityColorState(targets);
writePointCloudColors(modelId, preset.colorize);
viewer?.scene?.glRedraw?.();
};
const applyDisplayModeToModel = (modelId) => {
const model = sceneModels[modelId] || viewer?.scene?.models?.[modelId];
if (!model) return;
@ -450,6 +537,11 @@ const applyDisplayModeToModel = (modelId) => {
const objects = Object.values(model.objects || {});
const targets = objects.length ? objects : [model];
if (isPointCloudModel(modelId)) {
applyPointCloudDisplayMode(modelId, preset, targets);
return;
}
targets.forEach((entity) => {
if (!entity) return;
try {
@ -1599,6 +1691,7 @@ const destroyAllModels = ({ preserveMeta = false } = {}) => {
activeModels.length = 0;
Object.keys(sceneModels).forEach((key) => delete sceneModels[key]);
Object.keys(modelTypes).forEach((key) => delete modelTypes[key]);
pointCloudColorSnapshots.clear();
if (!preserveMeta) {
Object.keys(transformStore).forEach((key) => delete transformStore[key]);
}
@ -1717,6 +1810,7 @@ const deleteModelById = (modelId) => {
activeModels.splice(idx, 1);
delete sceneModels[modelId];
delete modelTypes[modelId];
pointCloudColorSnapshots.delete(modelId);
delete transformStore[modelId];
treeModelIds.delete(modelId);
if (customTrees.has(modelId)) {
@ -2929,6 +3023,9 @@ const initViewer = async () => {
setStatus(`Загружено: ${name || inferredType}`);
dropZone.classList.add("hidden");
setLoading(false);
if (inferredType === "las") {
snapshotPointCloudColors(id);
}
applyDisplayModeToModel(id);
updateNavCubeVisibility();
updatePanelsVisibility();

View File

@ -239,6 +239,6 @@
<input id="fileInput" class="hidden" type="file"
accept=".xkt,.glb,.gltf,.bim,.las,.laz,.obj,.stl">
<script type="module" src="./dcViewer.js?v=13"></script>
<script type="module" src="./dcViewer.js?v=14"></script>
</body>
</html>