2026-05-07-17-05-43 增加3D实体显示档位

This commit is contained in:
2026-05-07 17:09:18 +08:00
parent bbc7d215e9
commit 97f5c78907
6 changed files with 188 additions and 8 deletions

View File

@@ -26,7 +26,7 @@ import { api, downloadDicomArchive, downloadMask } from '../lib/api';
type Plane = 'axial' | 'sagittal' | 'coronal';
type DisplayMode = DicomPreview['mode'];
type SolidityLevel = 'preview' | 'standard' | 'fine' | 'ultra';
type SolidityLevel = 'standard' | 'fine' | 'ultra' | 'solid';
interface ModuleStyle {
visible: boolean;
@@ -59,10 +59,10 @@ type ModelPoseKey = keyof ModelPose;
const defaultModuleColors = ['#3b82f6', '#22c55e', '#f59e0b', '#ef4444', '#8b5cf6', '#14b8a6', '#f97316', '#64748b', '#ec4899'];
const solidityOptions: Array<{ id: SolidityLevel; label: string; limit: number }> = [
{ id: 'preview', label: '预览', limit: 6000 },
{ id: 'standard', label: '标准', limit: 16000 },
{ id: 'fine', label: '精细', limit: 36000 },
{ id: 'ultra', label: '超精细', limit: 72000 },
{ id: 'solid', label: '实体', limit: 200000 },
];
const defaultModelPose: ModelPose = {
rotateX: 0,
@@ -291,6 +291,7 @@ function NativeStlViewer({
files,
styles,
detailLimit,
solidMode,
pose,
onPoseChange,
}: {
@@ -298,6 +299,7 @@ function NativeStlViewer({
files: string[];
styles: Record<string, ModuleStyle>;
detailLimit: number;
solidMode: boolean;
pose: ModelPose;
onPoseChange: React.Dispatch<React.SetStateAction<ModelPose>>;
}) {
@@ -491,13 +493,14 @@ function NativeStlViewer({
geometry.setAttribute('position', new THREE.Float32BufferAttribute(payload.vertices, 3));
geometry.computeVertexNormals();
const style = styles[fileName] ?? { color: '#3b82f6', opacity: 0.72, visible: true };
const materialOpacity = solidMode ? Math.max(style.opacity, 0.94) : style.opacity;
const mesh = new THREE.Mesh(
geometry,
new THREE.MeshStandardMaterial({
color: style.color,
opacity: style.opacity,
transparent: style.opacity < 1,
roughness: 0.42,
opacity: materialOpacity,
transparent: materialOpacity < 1,
roughness: solidMode ? 0.56 : 0.42,
metalness: 0.04,
side: THREE.DoubleSide,
}),
@@ -600,7 +603,7 @@ function NativeStlViewer({
});
container.innerHTML = '';
};
}, [projectId, files.join('|'), JSON.stringify(styles), detailLimit]);
}, [projectId, files.join('|'), JSON.stringify(styles), detailLimit, solidMode]);
return (
<div className="h-full w-full relative cursor-grab active:cursor-grabbing">
@@ -696,7 +699,7 @@ export default function ProjectLibrary({ onReverse }: { onReverse: (projId: stri
];
const allModulesVisible = stlFiles.length > 0 && stlFiles.every((file) => moduleStyles[file]?.visible !== false);
const sliceTotal = dicomPreview?.total ?? selectedProject?.dicomCount ?? 0;
const selectedSolidity = solidityOptions.find((option) => option.id === solidityLevel) ?? solidityOptions[1];
const selectedSolidity = solidityOptions.find((option) => option.id === solidityLevel) ?? solidityOptions[0];
useEffect(() => {
const next: Record<string, ModuleStyle> = {};
@@ -1235,6 +1238,7 @@ export default function ProjectLibrary({ onReverse }: { onReverse: (projId: stri
files={stlFiles}
styles={moduleStyles}
detailLimit={selectedSolidity.limit}
solidMode={solidityLevel === 'solid'}
pose={modelPose}
onPoseChange={setModelPose}
/>